module klang.编译.APInt.APInt_;
import 全局;
import std.conv: ·to = to;
import klang.编译.核心.核心_: 创建数组, 返回零值, 最小, rangeEquals, 字节转换, bitTo, BitsToDouble, BitsToFloat, DoubleToBits, FloatToBits;
import klang.编译.类型.枚举值.枚举值_: 字符_;
import 编译数字 = 编译数字.编译;
import klang.编译.系统.系统_: sys;
alias WordType_ = ulong;
alias 正整数32类型_ = uint;
alias _CHAR_BIT类型 = char;
uint CHAR_BIT;
ulong APINT_WORD_SIZE;
ulong APINT_BITS_PER_WORD;
ulong UINT64_MAX = 18446744073709551615;
uint UINT32_MAX = 4294967295;
int INT_MAX = 2147483647;
int INT_MIN;
ulong WORDTYPE_MAX;
ubyte[256] BitReverseTable256;
ubyte[32] _sqrtResults;
static this() {
    CHAR_BIT = (cast(uint)(_CHAR_BIT类型.sizeof));
    APINT_WORD_SIZE = (cast(ulong)(WordType_.sizeof));
    APINT_BITS_PER_WORD = .APINT_WORD_SIZE * 8;
    INT_MIN = (-2147483647 - 1);
    WORDTYPE_MAX = ~(cast(WordType_)(0));
    BitReverseTable256 = [
        0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 8,
        136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 4, 132,
        68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 12, 140, 76,
        204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 2, 130, 66, 194,
        34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 10, 138, 74, 202, 42,
        170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 6, 134, 70, 198, 38, 166,
        102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 14, 142, 78, 206, 46, 174,
        110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 1, 129, 65, 193, 33, 161, 97,
        225, 17, 145, 81, 209, 49, 177, 113, 241, 9, 137, 73, 201, 41, 169, 105, 233,
        25, 153, 89, 217, 57, 185, 121, 249, 5, 133, 69, 197, 37, 165, 101, 229, 21,
        149, 85, 213, 53, 181, 117, 245, 13, 141, 77, 205, 45, 173, 109, 237, 29,
        157, 93, 221, 61, 189, 125, 253, 3, 131, 67, 195, 35, 163, 99, 227, 19, 147,
        83, 211, 51, 179, 115, 243, 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91,
        219, 59, 187, 123, 251, 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215,
        55, 183, 119, 247, 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63,
        191, 127, 255
    ];
    _sqrtResults = [
        /*     0 */ 0,
        /*  1- 2 */ 1, 1,
        /*  3- 6 */ 2, 2, 2, 2,
        /*  7-12 */ 3, 3, 3, 3, 3, 3,
        /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4,
        /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
        /*    31 */ 6
    ];
}
enum Rounding : int {
    DOWN = 0,
    TOWARD_ZERO = 1,
    UP = 2
}
class APInt_ {
    ulong[] U;
    uint BitWidth;
    this() {
        this.BitWidth = 1;
        this.U = 创建数组!(ulong)();
        this.U.length = 1;
    }
    this(uint numBits, ulong val, bool isSigned = false) {
        this.BitWidth = numBits;
        this.U = 创建数组!(ulong)();
        this.U.length = 1;
        if (this.isSingleWord()) {
            this.U[0] = val;
        }
        else {
            this.initSlowCase(val, isSigned);
        }
    }
    this(ulong[] val, uint bits) {
        this.BitWidth = bits;
        this.U = val;
    }
    this(APInt_ that) {
        this.BitWidth = that.BitWidth;
        this.U = 创建数组!(ulong)();
        this.U.length = 1;
        if (this.isSingleWord()) {
            this.U = that.U;
        }
        else {
            this.initSlowCase(that);
        }
    }
    this(uint numBits, ulong[] bigVal) {
        this.BitWidth = numBits;
        this.U = 创建数组!(ulong)();
        this.U.length = 1;
        this.initFromArray(bigVal);
    }
    this(uint numBits, dstring str, ubyte radix) {
        this.BitWidth = numBits;
        this.U = 创建数组!(ulong)();
        this.U.length = 1;
        this.fromString(numBits, str, radix);
    }
    uint getBitWidth() { return this.BitWidth; }
    bool isSingleWord() {
        return this.BitWidth <= .APINT_BITS_PER_WORD;
    }
    void initSlowCase(ulong val, bool isSigned) {
        this.U = .getClearedMemory(this.getNumWords());
        this.U[0] = val;
        if (isSigned && (cast(long)(val)) < 0) {
            {
                for (uint i = 1; i < this.getNumWords(); ++i) {
                    this.U[i] = .WORDTYPE_MAX;
                }
            }
        }
        this.clearUnusedBits();
    }
    void initSlowCase(ref APInt_ that) {
        this.U = .getClearedMemory(this.getNumWords());
        .·memcpy(this.U.ptr, that.U.ptr, this.getNumWords() * .APINT_WORD_SIZE);
    }
    void initFromArray(ulong[] bigVal) {
        if (this.isSingleWord()) {
            this.U[0] = bigVal[0];
        }
        else {
            this.U = .getClearedMemory(this.getNumWords());
            .·memcpy(this.U.ptr, bigVal.ptr, this.getNumWords() * .APINT_WORD_SIZE);
        }
        this.clearUnusedBits();
    }
    void fromString(uint numbits, dstring str, ubyte radix) {
        long 开始 = 0;
        dchar p = (cast()(str[开始]));
        size_t 长度 = str.length;
        bool isNeg = p == cast(dchar)'-';
        if (p == cast(dchar)'-' || p == cast(dchar)'+') {
            ++开始;
            p = (cast()(str[开始]));
        }
        if (this.isSingleWord()) {
            this.U[0] = 0;
        }
        else {
            this.U = .getClearedMemory(this.getNumWords());
        }
        ubyte shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0);
        {
            for (long i = 开始; i < 长度; ++i) {
                p = (cast()(str[i]));
                uint digit = .getDigit(p, radix);
                if (shift != 0) {
                    this.Op左移等(shift);
                }
                else {
                    this.Op乘等(radix);
                }
                this.Op加等(digit);
            }
        }
        if (isNeg) {
            this.negate();
        }
    }
    uint getNumWords() {
        return .getNumWords(this.BitWidth);
    }
    void setBit(uint BitPosition) {
        ulong Mask = .maskBit(BitPosition);
        if (this.isSingleWord()) {
            this.U[0] |= Mask;
        }
        else {
            this.U[.whichWord(BitPosition)] |= Mask;
        }
    }
    void clearBit(uint BitPosition) {
        ulong Mask = ~.maskBit(BitPosition);
        if (this.isSingleWord()) {
            this.U[0] &= Mask;
        }
        else {
            this.U[.whichWord(BitPosition)] &= Mask;
        }
    }
    APInt_ clearUnusedBits() {
        uint WordBits = (cast(uint)(((this.BitWidth - 1) % .APINT_BITS_PER_WORD) + 1));
        ulong mask = .WORDTYPE_MAX >> (.APINT_BITS_PER_WORD - WordBits);
        if (this.BitWidth == 0) {
            mask = 0;
        }
        if (this.isSingleWord()) {
            this.U[0] &= mask;
        }
        else {
            this.U[this.getNumWords() - 1] &= mask;
        }
        return this;
    }
    APInt_ Op负() {
        this.negate();
        return this;
    }
    bool Op索引访问(uint bitPosition) {
        return (.maskBit(bitPosition) & this.getWord(bitPosition)) != 0;
    }
    APInt_ Op异或等(APInt_ RHS) {
        if (this.isSingleWord()) {
            this.U[0] ^= RHS.U[0];
        }
        else {
            this.XorAssignSlowCase(RHS);
        }
        return this;
    }
    APInt_ Op异或等(ulong RHS) {
        this.U[0] ^= RHS;
        return this;
    }
    APInt_ Op等(APInt_ RHS) {
        if (this.isSingleWord() && RHS.isSingleWord()) {
            this.U[0] = RHS.U[0];
            this.BitWidth = RHS.BitWidth;
            return this.clearUnusedBits();
        }
        this.AssignSlowCase(RHS);
        return this;
    }
    APInt_ Op等(ulong RHS) {
        if (this.isSingleWord()) {
            this.U[0] = RHS;
            return this.clearUnusedBits();
        }
        this.U[0] = RHS;
        {
            for (int i = 1; i < this.U.length; ++i) {
                this.U[i] = 0;
            }
        }
        return this;
    }
    APInt_ Op加等(ulong RHS) {
        if (this.isSingleWord()) {
            this.U[0] += RHS;
        }
        else {
            .tcAddPart(this.U, RHS, this.getNumWords());
        }
        return this.clearUnusedBits();
    }
    APInt_ Op加等(APInt_ RHS) {
        if (this.isSingleWord()) {
            this.U[0] += RHS.U[0];
        }
        else {
            .tcAdd(this.U, RHS.U, 0, this.getNumWords());
        }
        return this.clearUnusedBits();
    }
    APInt_ Op加加() {
        if (this.isSingleWord()) {
            ++this.U[0];
        }
        else {
            .tcIncrement(this.U, this.getNumWords());
        }
        return this.clearUnusedBits();
    }
    APInt_ Op减减() {
        if (this.isSingleWord()) {
            --this.U[0];
        }
        else {
            .tcDecrement(this.U, this.getNumWords());
        }
        return this.clearUnusedBits();
    }
    APInt_ Op左移等(uint ShiftAmt) {
        if (this.isSingleWord()) {
            if (ShiftAmt == this.BitWidth) {
                this.U[0] = 0;
            }
            else {
                this.U[0] <<= ShiftAmt;
            }
            return this.clearUnusedBits();
        }
        else {
            this.shlSlowCase(ShiftAmt);
            return this;
        }
    }
    APInt_ Op左移等(APInt_ shiftAmt) {
        // It's undefined behavior in C to shift by BitWidth or greater.
        this.Op左移等((cast(uint)(shiftAmt.getLimitedValue(this.BitWidth))));
        return this;
    }
    APInt_ Op左移(uint Bits) {
        return this.shl(Bits);
    }
    APInt_ Op左移(APInt_ Bits) {
        return this.shl(Bits);
    }
    APInt_ Op乘(APInt_ RHS) {
        if (this.isSingleWord()) {
            return new APInt_(this.BitWidth, this.U[0] * RHS.U[0]);
        }
        APInt_ 结果 = new APInt_(this.BitWidth, .getClearedMemory(this.getNumWords()));
        .tcMultiply(结果.U, this.U, RHS.U, this.getNumWords());
        结果.clearUnusedBits();
        return 结果;
    }
    APInt_ Op乘等(APInt_ RHS) {
        APInt_ 结果 = this.Op乘(RHS);
        this.BitWidth = 结果.BitWidth;
        this.U = 结果.U;
        return this;
    }
    APInt_ Op乘等(ulong RHS) {
        if (this.isSingleWord()) {
            this.U[0] *= RHS;
        }
        else {
            uint NumWords = this.getNumWords();
            .tcMultiplyPart(this.U, this.U, RHS, 0, NumWords, NumWords, false);
        }
        return this.clearUnusedBits();
    }
    APInt_ Op且等(APInt_ RHS) {
        if (this.isSingleWord()) {
            this.U[0] &= RHS.U[0];
        }
        else {
            this.AndAssignSlowCase(RHS);
        }
        return this;
    }
    APInt_ Op且等(ulong RHS) {
        if (this.isSingleWord()) {
            this.U[0] &= RHS;
            return this;
        }
        else {
            {
                for (int i = 0; i < this.U.length; ++i) {
                    this.U[i] = 0;
                }
            }
            this.U[0] &= RHS;
        }
        return this;
    }
    bool Op等等(ulong Val) {
        return (this.isSingleWord() || this.getActiveBits() <= 64) && this.getZExtValue() == Val;
    }
    bool Op等等(APInt_ RHS) {
        if (this.isSingleWord()) {
            return this.U[0] == RHS.U[0];
        }
        return this.EqualSlowCase(RHS);
    }
    APInt_ Op减等(APInt_ RHS) {
        if (this.isSingleWord()) {
            this.U[0] -= RHS.U[0];
        }
        else {
            .tcSubtract(this.U, RHS.U, 0, this.getNumWords());
        }
        return this.clearUnusedBits();
    }
    APInt_ Op减等(ulong RHS) {
        if (this.isSingleWord()) {
            this.U[0] -= RHS;
        }
        else {
            .tcSubtractPart(this.U, RHS, this.getNumWords());
        }
        return this.clearUnusedBits();
    }
    APInt_ Op或等(APInt_ RHS) {
        if (this.isSingleWord()) {
            this.U[0] |= RHS.U[0];
        }
        else {
            this.OrAssignSlowCase(RHS);
        }
        return this;
    }
    APInt_ Op或等(ulong RHS) {
        this.U[0] |= RHS;
        return this;
    }
    APInt_ abs() {
        if (this.isNegative()) {
            return this.Op负();
        }
        return this;
    }
    bool eq(APInt_ RHS) {
        return this.Op等等(RHS);
    }
    void AndAssignSlowCase(APInt_ RHS) {
        .tcAnd(this.U, RHS.U, this.getNumWords());
    }
    void AssignSlowCase(ref APInt_ RHS) {
        this.reallocate(RHS.BitWidth);
        this.U = RHS.U;
    }
    void flipAllBitsSlowCase() {
        .tcComplement(this.U, this.getNumWords());
        this.clearUnusedBits();
    }
    void flipAllBits() {
        if (this.isSingleWord()) {
            this.U[0] ^= .WORDTYPE_MAX;
            this.clearUnusedBits();
        }
        else {
            this.flipAllBitsSlowCase();
        }
    }
    void negate() {
        this.flipAllBits();
        this.Op加等(1);
    }
    void shlSlowCase(uint ShiftAmt) {
        .tcShiftLeft(this.U, this.getNumWords(), ShiftAmt);
        this.clearUnusedBits();
    }
    bool isZero() {
        return .tcIsZero(this.U, this.getNumWords());
    }
    bool isMinusOne() {
        return this.isAllOnesValue();
    }
    ulong getLimitedValue(ulong Limit = .UINT64_MAX) {
        return this.ugt(Limit) ? Limit : this.getZExtValue();
    }
    ulong getZExtValue() {
        return this.U[0];
    }
    long getSExtValue() {
        if (this.isSingleWord()) {
            return .SignExtend64(this.U[0], this.BitWidth);
        }
        return (cast(long)(this.U[0]));
    }
    dstring 打印(bool isSigned = false) {
        return this.打印文本(10, isSigned, false);
    }
    dstring toStringUnsigned(uint Radix = 10) {
        return this.打印文本(Radix, false, false);
    }
    dstring toStringSigned(uint Radix = 10) {
        return this.打印文本(Radix, true, false);
    }
    dstring 打印文本(uint Radix, bool Signed, bool formatAsCLiteral) {
        dstring 前缀 = ""d;
        if (formatAsCLiteral) {
            switch (Radix) {
                case 2: {
                    前缀 = "0b"d;
                    break;
                }
                case 8: {
                    前缀 = "0"d;
                    break;
                }
                case 16: {
                    前缀 = "0x"d;
                    break;
                }
                default: {
                    break;
                }
            }
        }
        if (this.isZero()) {
            return 前缀 ~ "0"d;
        }
        dstring 词典 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"d;
        if (this.isSingleWord()) {
            ulong N = 0;
            if (!Signed) {
                N = this.getZExtValue();
            }
            else {
                ulong I = this.getSExtValue();
                if (I >= 0) {
                    N = I;
                }
                else {
                    前缀 ~= "-"d;
                    N = -(cast(ulong)(I));
                }
            }
            dchar[] chs = 创建数组!(dchar)();
            chs.length = 65;
            size_t 开始 = chs.length;
            while(N != 0) {
                immutable(dchar) ch = 词典[N % Radix];
                chs[--开始] = (cast()(ch));
                N /= Radix;
            }
            return 前缀 ~ ·to!(dstring)(chs[开始 .. $]);
        }
        dstring 输出 = ""d;
        APInt_ aa = this;
        APInt_ Tmp = new APInt_(aa);
        if (Signed && this.isNegative()) {
            Tmp.negate();
            输出 ~= "-"d;
        }
        if (Radix == 2 || Radix == 8 || Radix == 16) {
            uint ShiftAmt = (Radix == 16 ? 4 : (Radix == 8 ? 3 : 1));
            uint MaskAmt = Radix - 1;
            while(Tmp.getBoolValue()) {
                uint Digit = (cast(uint)(Tmp.getRawData()[0])) & MaskAmt;
                输出 = ·to!(dstring)(词典[Digit]) ~ 输出;
                Tmp.lshrInPlace(ShiftAmt);
            }
        }
        else {
            while(Tmp.getBoolValue()) {
                ulong Digit = 0;
                .udivrem(Tmp, Radix, Tmp, Digit);
                输出 = ·to!(dstring)(词典[Digit]) ~ 输出;
            }
        }
        return 前缀 ~ 输出;
    }
    void lshrSlowCase(uint ShiftAmt) {
        .tcShiftRight(this.U, this.getNumWords(), ShiftAmt);
    }
    bool getBoolValue() {
        return !this.isZero();
    }
    ulong[] getRawData() {
        return this.U;
    }
    bool isNegative() {
        return this.Op索引访问(this.BitWidth - 1) != 0;
    }
    bool isNonNegative() { return !this.isNegative(); }
    bool isSignBitSet() { return this.Op索引访问(this.BitWidth - 1); }
    bool isSignBitClear() { return !this.isSignBitSet(); }
    bool isStrictlyPositive() { return this.isNonNegative() && !this.isNullValue(); }
    bool isNonPositive() { return !this.isStrictlyPositive(); }
    bool isNullValue() { APInt_ ···temp·0·_1 = this; return ···temp·0·_1 is ··null!(APInt_); }
    bool isOneValue() {
        if (this.isSingleWord()) {
            return this.U[0] == 1;
        }
        return this.countLeadingZerosSlowCase() == this.BitWidth - 1;
    }
    bool isOne() {
        return this.isOneValue();
    }
    bool isMaxValue() { return this.isAllOnesValue(); }
    bool isAllOnesValue() {
        if (this.isSingleWord()) {
            return this.U[0] == .WORDTYPE_MAX >> (.APINT_BITS_PER_WORD - this.BitWidth);
        }
        return this.countTrailingOnesSlowCase() == this.BitWidth;
    }
    APInt_ byteSwap() {
        if (this.BitWidth == 16) {
            return new APInt_(this.BitWidth, .ByteSwap_16((cast(ushort)(this.U[0]))));
        }
        if (this.BitWidth == 32) {
            return new APInt_(this.BitWidth, .ByteSwap_32((cast(uint)(this.U[0]))));
        }
        if (this.BitWidth <= 64) {
            ulong Tmp1 = .ByteSwap_64(this.U[0]);
            Tmp1 >>= (64 - this.BitWidth);
            return new APInt_(this.BitWidth, Tmp1);
        }
        APInt_ Result = new APInt_((cast(uint)(this.getNumWords() * .APINT_BITS_PER_WORD)), 0);
        {
            uint I = 0;
            uint N = this.getNumWords();
            for (; I != N; ++I) {
                Result.U[I] = .ByteSwap_64(this.U[N - I - 1]);
            }
        }
        if (Result.BitWidth != this.BitWidth) {
            Result.lshrInPlace(Result.BitWidth - this.BitWidth);
            Result.BitWidth = this.BitWidth;
        }
        return Result;
    }
    uint logBase2() { return this.getActiveBits() - 1; }
    uint ceilLogBase2() {
        APInt_ temp = new APInt_(this);
        temp.Op减减();
        return temp.getActiveBits();
    }
    ulong nearestLogBase2() {
        // Special 若是 when we have a bitwidth of 1. If VAL is 1, then we
        // get 0. If VAL is 0, we get WORDTYPE_MAX which gets truncated to
        // UINT32_MAX.
        if (this.BitWidth == 1) {
            return this.U[0] - 1;
        }
        // Handle the zero 若是.
        if (this.isNullValue()) {
            return .UINT32_MAX;
        }
        // The non-zero 若是 is handled by computing:
        //
        //   nearestLogBase2(x) = logBase2(x) + x[logBase2(x)-1].
        //
        // where x[i] is referring to the value of the ith bit of x.
        uint lg = this.logBase2();
        return lg + (cast(uint)((this).Op索引访问(lg - 1) ? 1 : 0));
    }
    int exactLogBase2() {
        if (!this.isPowerOf2()) {
            return -1;
        }
        return this.logBase2();
    }
    void reallocate(uint NewBitWidth) {
        if (this.getNumWords() == .getNumWords(NewBitWidth)) {
            this.BitWidth = NewBitWidth;
            return;
        }
        this.U.length = 0;
        this.BitWidth = NewBitWidth;
        if (!this.isSingleWord()) {
            this.U = .getClearedMemory(this.getNumWords());
        }
    }
    uint getActiveBits() {
        return this.BitWidth - this.countLeadingZeros();
    }
    uint countLeadingZeros() {
        if (this.isSingleWord()) {
            uint unusedBits = (cast(uint)(.APINT_BITS_PER_WORD - this.BitWidth));
            return .llvm_countLeadingZeros_64(this.U[0]) - unusedBits;
        }
        return this.countLeadingZerosSlowCase();
    }
    uint getNumSignBits() {
        return this.isNegative() ? this.countLeadingOnes() : this.countLeadingZeros();
    }
    uint countLeadingZerosSlowCase() {
        uint Count = 0;
        {
            for (int i = this.getNumWords() - 1; i >= 0; --i) {
                ulong V = this.U[i];
                if (V == 0) {
                    Count += (cast(uint)(.APINT_BITS_PER_WORD));
                }
                else {
                    Count += .llvm_countLeadingZeros_64(V);
                    break;
                }
            }
        }
        // Adjust for unused bits in the most significant word (they are zero).
        ulong Mod = this.BitWidth % .APINT_BITS_PER_WORD;
        Count -= Mod > 0 ? (cast(uint)(.APINT_BITS_PER_WORD - Mod)) : 0;
        return Count;
    }
    uint countLeadingOnes() {
        if (this.isSingleWord()) {
            return .llvm_countLeadingZeros_64(this.U[0] << (.APINT_BITS_PER_WORD - this.BitWidth));
        }
        return this.countLeadingOnesSlowCase();
    }
    uint countLeadingOnesSlowCase() {
        uint highWordBits = (cast(uint)(this.BitWidth % .APINT_BITS_PER_WORD));
        uint shift = 0;
        if (highWordBits == 0) {
            highWordBits = (cast(uint)(.APINT_BITS_PER_WORD));
            shift = 0;
        }
        else {
            shift = (cast(uint)(.APINT_BITS_PER_WORD - highWordBits));
        }
        int i = (cast(int)(this.getNumWords() - 1));
        uint Count = .llvm_countLeadingOnes(this.U[i] << shift);
        if (Count == highWordBits) {
            for (--i; i >= 0; --i) {
                if (this.U[i] == .WORDTYPE_MAX) {
                    Count += (cast(uint)(.APINT_BITS_PER_WORD));
                }
                else {
                    Count += .llvm_countLeadingOnes(this.U[i]);
                    break;
                }
            }
        }
        return Count;
    }
    uint countTrailingOnesSlowCase() {
        uint Count = 0;
        uint i = 0;
        for (; i < this.getNumWords() && this.U[i] == .WORDTYPE_MAX; ++i) {
            Count += (cast(uint)(.APINT_BITS_PER_WORD));
        }
        if (i < this.getNumWords()) {
            Count += .llvm_countTrailingZeros_64(this.U[i]);
        }
        return Count;
    }
    bool EqualSlowCase(APInt_ RHS) {
        return rangeEquals!(ulong)(this.U, RHS.U, 0, 0);
    }
    int compare(APInt_ RHS) {
        assert(this.BitWidth == RHS.BitWidth, "Bit widths must be same for comparison"c);
        if (this.isSingleWord()) {
            return this.U[0] < RHS.U[0] ? -1 : this.U[0] == RHS.U[0] ? 0 : 1;
        }
        return .tcCompare(this.U, RHS.U, this.getNumWords());
    }
    int compareSigned(APInt_ RHS) {
        if (this.isSingleWord()) {
            long lhsSext = .SignExtend64(this.U[0], this.BitWidth);
            long rhsSext = .SignExtend64(RHS.U[0], this.BitWidth);
            return lhsSext < rhsSext ? -1 : lhsSext == rhsSext ? 0 : 1;
        }
        bool lhsNeg = this.isNegative();
        bool rhsNeg = RHS.isNegative();
        // If the sign bits don't match, then (LHS < RHS) if LHS is negative
        if (lhsNeg != rhsNeg) {
            return lhsNeg ? -1 : 1;
        }
        // Otherwise we can just use an 正整数32 comparison, because even negative
        // numbers compare correctly this way if both have the same signed-ness.
        return .tcCompare(this.U, RHS.U, this.getNumWords());
    }
    uint getMinSignedBits() { return this.BitWidth - this.getNumSignBits() + 1; }
    uint countTrailingZeros() {
        if (this.isSingleWord()) {
            uint TrailingZeros = .llvm_countTrailingZeros_64(this.U[0]);
            return (TrailingZeros > this.BitWidth ? this.BitWidth : TrailingZeros);
        }
        return this.countTrailingZerosSlowCase();
    }
    uint countTrailingZerosSlowCase() {
        uint Count = 0;
        uint i = 0;
        for (; i < this.getNumWords() && this.U[i] == 0; ++i) {
            Count += (cast(uint)(.APINT_BITS_PER_WORD));
        }
        if (i < this.getNumWords()) {
            Count += .llvm_countTrailingZeros_64(this.U[i]);
        }
        return (cast(uint)(最小(Count, this.BitWidth)));
    }
    APInt_ udiv(APInt_ RHS) {
        // First, deal with the easy case
        if (this.isSingleWord()) {
            return new APInt_(this.BitWidth, this.U[0] / RHS.U[0]);
        }
        // Get some facts about the LHS and RHS number of bits and words
        uint lhsWords = .getNumWords(this.getActiveBits());
        uint rhsBits = RHS.getActiveBits();
        uint rhsWords = .getNumWords(rhsBits);
        // Deal with some degenerate cases
        if (lhsWords == 0) {
            // 0 / X ===> 0
            return new APInt_(this.BitWidth, 0);
        }
        if (rhsBits == 1) {
            // X / 1 ===> X
            return this;
        }
        if (lhsWords < rhsWords || this.ult(RHS)) {
            // X / Y ===> 0, iff X < Y
            return new APInt_(this.BitWidth, 0);
        }
        if (this.Op等等(RHS)) {
            // X / X ===> 1
            return new APInt_(this.BitWidth, 1);
        }
        if (lhsWords == 1) { // rhsWords is 1 如果 lhsWords is 1.
            // All high words are zero, just use native divide
            return new APInt_(this.BitWidth, this.U[0] / RHS.U[0]);
        }
        // We have to compute it the hard way. Invoke the Knuth divide algorithm.
        APInt_ Quotient = new APInt_(this.BitWidth, 0); // to hold result.
        ulong[] re = [];
        .divide(this.U, lhsWords, RHS.U, rhsWords, Quotient.U, re);
        return Quotient;
    }
    APInt_ udiv(ulong RHS) {
        // First, deal with the easy case
        if (this.isSingleWord()) {
            return new APInt_(this.BitWidth, this.U[0] / RHS);
        }
        // Get some facts about the LHS words.
        uint lhsWords = .getNumWords(this.getActiveBits());
        // Deal with some degenerate cases
        if (lhsWords == 0) {
            // 0 / X ===> 0
            return new APInt_(this.BitWidth, 0);
        }
        if (RHS == 1) {
            // X / 1 ===> X
            return this;
        }
        if (this.ult(RHS)) {
            // X / Y ===> 0, iff X < Y
            return new APInt_(this.BitWidth, 0);
        }
        if (this.Op等等(RHS)) {
            // X / X ===> 1
            return new APInt_(this.BitWidth, 1);
        }
        if (lhsWords == 1) { // rhsWords is 1 如果 lhsWords is 1.
            // All high words are zero, just use native divide
            return new APInt_(this.BitWidth, this.U[0] / RHS);
        }
        // We have to compute it the hard way. Invoke the Knuth divide algorithm.
        APInt_ Quotient = new APInt_(this.BitWidth, 0); // to hold result.
        ulong[] rhs = [RHS];
        ulong[] re = [];
        .divide(this.U, lhsWords, rhs, 1, Quotient.U, re);
        return Quotient;
    }
    bool isSubsetOfSlowCase(APInt_ RHS) {
        {
            uint i = 0;
            uint e = this.getNumWords();
            for (; i != e; ++i) {
                if ((this.U[i] & ~RHS.U[i]) != 0) {
                    return false;
                }
            }
        }
        return true;
    }
    bool intersectsSlowCase(APInt_ RHS) {
        {
            uint i = 0;
            uint e = this.getNumWords();
            for (; i != e; ++i) {
                if ((this.U[i] & RHS.U[i]) != 0) {
                    return true;
                }
            }
        }
        return false;
    }
    void setBitsSlowCase(uint loBit, uint hiBit) {
        uint loWord = (cast(uint)(.whichWord(loBit)));
        uint hiWord = (cast(uint)(.whichWord(hiBit)));
        // Create an initial mask 循环 the low word with zeros below loBit.
        ulong loMask = .WORDTYPE_MAX << .whichBit(loBit);
        // If hiBit is not aligned, we need a high mask.
        uint hiShiftAmt = (cast(uint)(.whichBit(hiBit)));
        if (hiShiftAmt != 0) {
            // Create a high mask with zeros above hiBit.
            ulong hiMask = .WORDTYPE_MAX >> (.APINT_BITS_PER_WORD - hiShiftAmt);
            // If loWord and hiWord are equal, then we combine the masks. Otherwise,
            // set the bits in hiWord.
            if (hiWord == loWord) {
                loMask &= hiMask;
            }
            else {
                this.U[hiWord] |= hiMask;
            }
        }
        // Apply the mask to the low word.
        this.U[loWord] |= loMask;
        {
            // Fill any words between loWord and hiWord with all ones.
            for (uint word = loWord + 1; word < hiWord; ++word) {
                this.U[word] = .WORDTYPE_MAX;
            }
        }
    }
    void flipBit(uint bitPosition) {
        this.setBitVal(bitPosition, this.Op索引访问(bitPosition));
    }
    void setBitVal(uint BitPosition, bool BitValue) {
        if (BitValue) {
            this.setBit(BitPosition);
        }
        else {
            this.clearBit(BitPosition);
        }
    }
    double roundToDouble(bool isSigned) {
        // Handle the simple 若是 where the value is contained in one 正整数64.
        // It is wrong to optimize getWord(0) to VAL; there might be more than one word.
        if (this.isSingleWord() || this.getActiveBits() <= .APINT_BITS_PER_WORD) {
            if (isSigned) {
                long sext = .SignExtend64(this.getWord(0), this.BitWidth);
                return (cast(double)(sext));
            }
            else {
                return (cast(double)(this.getWord(0)));
            }
        }
        // Determine 如果 the value is negative.
        bool isNeg = isSigned ? this.Op索引访问(this.BitWidth - 1) : false;
        // Construct the absolute value 如果 we're negative.
        APInt_ 临时 = isNeg ? this.Op负() : this;
        APInt_ Tmp = new APInt_(临时);
        // Figure out how many bits we're using.
        uint n = Tmp.getActiveBits();
        // The exponent (without bias normalization) is just the number of bits
        // we are using. Note that the sign bit is gone since we constructed the
        // absolute value.
        ulong exp = n;
        // Return infinity 循环 exponent overflow
        if (exp > 1023) {
            if (!isSigned || !isNeg) {
                return 编译数字.编译!(double)("inf"d, 10);
            }
            else {
                return 编译数字.编译!(double)("-inf"d, 10);
            }
        }
        exp += 1023; // Increment 循环 1023 bias
        // Number of bits in mantissa is 52. To obtain the mantissa value, we must
        // extract the high 52 bits from the correct words in pVal.
        ulong mantissa;
        uint hiWord = (cast(uint)(.whichWord(n - 1)));
        if (hiWord == 0) {
            mantissa = Tmp.U[0];
            if (n > 52) {
                mantissa >>= n - 52; // shift down, we want the top 52 bits.
            }
        }
        else {
            ulong hibits = Tmp.U[hiWord] << (52 - n % .APINT_BITS_PER_WORD);
            ulong lobits = Tmp.U[hiWord - 1] >> (11 + n % .APINT_BITS_PER_WORD);
            mantissa = hibits | lobits;
        }
        // The leading bit of mantissa is implicit, so get rid of it.
        ulong sign = isNeg ? (1uL << (.APINT_BITS_PER_WORD - 1)) : 0;
        ulong I = sign | (exp << 52) | mantissa;
        return 字节转换!(double, ulong)(I);
    }
    double roundToDouble() { return this.roundToDouble(false); }
    double signedRoundToDouble() { return this.roundToDouble(true); }
    double bitsToDouble() {
        return BitsToDouble(this.getWord(0));
    }
    float bitsToFloat() {
        return BitsToFloat((cast(uint)((this.getWord(0)))));
    }
    void insertBits(APInt_ subBits, uint bitPosition) {
        uint subBitWidth = subBits.BitWidth;
        // Single word result can be done as a direct bitmask.
        if (this.isSingleWord()) {
            ulong mask = .WORDTYPE_MAX >> (.APINT_BITS_PER_WORD - subBitWidth);
            this.U[0] &= ~(mask << bitPosition);
            this.U[0] |= (subBits.U[0] << bitPosition);
            return;
        }
        uint loBit = (cast(uint)(.whichBit(bitPosition)));
        uint loWord = (cast(uint)(.whichWord(bitPosition)));
        uint hi1Word = (cast(uint)(.whichWord(bitPosition + subBitWidth - 1)));
        // Insertion within a single word can be done as a direct bitmask.
        if (loWord == hi1Word) {
            ulong mask = .WORDTYPE_MAX >> (.APINT_BITS_PER_WORD - subBitWidth);
            this.U[loWord] &= ~(mask << loBit);
            this.U[loWord] |= (subBits.U[0] << loBit);
            return;
        }
        // Insert on word boundaries.
        if (loBit == 0) {
            // Direct copy whole words.
            uint numWholeSubWords = (cast(uint)(subBitWidth / .APINT_BITS_PER_WORD));
            .·memcpy((cast(void*)(this.U[loWord .. $])), (cast(void*)(subBits.getRawData())), numWholeSubWords * .APINT_WORD_SIZE);
            // Mask+insert remaining bits.
            uint remainingBits = (cast(uint)(subBitWidth % .APINT_BITS_PER_WORD));
            if (remainingBits != 0) {
                ulong mask = .WORDTYPE_MAX >> (.APINT_BITS_PER_WORD - remainingBits);
                this.U[hi1Word] &= ~mask;
                this.U[hi1Word] |= subBits.getWord(subBitWidth - 1);
            }
            return;
        }
        {
            // General 若是 - set/clear individual bits in dst based on src.
            // TODO - there is scope 循环 optimization here, but at the moment 本体 code
            // path is barely used so prefer readability over performance.
            for (uint i = 0; i != subBitWidth; ++i) {
                this.setBitVal(bitPosition + i, (cast(byte[])(subBits.U))[i] != 0);
            }
        }
    }
    ulong getWord(uint bitPosition) {
        return this.isSingleWord() ? this.U[0] : this.U[.whichWord(bitPosition)];
    }
    APInt_ zext(uint width) {
        if (width <= .APINT_BITS_PER_WORD) {
            return new APInt_(width, this.U[0]);
        }
        APInt_ Result = new APInt_(.getClearedMemory(.getNumWords(width)), width);
        // Copy words.
        .·memcpy(Result.U.ptr, this.getRawData().ptr, this.getNumWords() * .APINT_WORD_SIZE);
        // Zero remaining words.
        .·memset(Result.U[this.getNumWords() .. $].ptr, 0, (Result.getNumWords() - this.getNumWords()) * .APINT_WORD_SIZE);
        return Result;
    }
    APInt_ trunc(uint width) {
        if (width <= .APINT_BITS_PER_WORD) {
            return new APInt_(width, this.getRawData()[0]);
        }
        APInt_ Result = new APInt_(.getClearedMemory(.getNumWords(width)), width);
        // Copy full words.
        uint i;
        for (i = 0; i != width / .APINT_BITS_PER_WORD; ++i) {
            Result.U[i] = this.U[i];
        }
        // Truncate and copy any partial word.
        uint bits = (cast(uint)((0 - width) % .APINT_BITS_PER_WORD));
        if (bits != 0) {
            Result.U[i] = (this.U[i] << bits) >> bits;
        }
        return Result;
    }
    APInt_ sext(uint Width) {
        if (Width <= .APINT_BITS_PER_WORD) {
            return new APInt_(Width, .SignExtend64(this.U[0], this.BitWidth));
        }
        APInt_ Result = new APInt_(.getClearedMemory(.getNumWords(Width)), Width);
        // Copy words.
        .·memcpy(Result.U.ptr, this.getRawData().ptr, this.getNumWords() * .APINT_WORD_SIZE);
        // Sign extend the last word since there may be unused bits in the input.
        Result.U[this.getNumWords() - 1] = .SignExtend64(Result.U[this.getNumWords() - 1], (cast(uint)(((this.BitWidth - 1) % .APINT_BITS_PER_WORD))) + 1);
        // Fill with sign bits.
        .·memset(Result.U[this.getNumWords() .. $].ptr, this.isNegative() ? -1 : 0, (Result.getNumWords() - this.getNumWords()) * .APINT_WORD_SIZE);
        Result.clearUnusedBits();
        return Result;
    }
    APInt_ zextOrTrunc(uint width) {
        if (this.BitWidth < width) {
            return this.zext(width);
        }
        if (this.BitWidth > width) {
            return this.trunc(width);
        }
        return this;
    }
    APInt_ sextOrTrunc(uint width) {
        if (this.BitWidth < width) {
            return this.sext(width);
        }
        if (this.BitWidth > width) {
            return this.trunc(width);
        }
        return this;
    }
    APInt_ truncOrSelf(uint width) {
        if (this.BitWidth > width) {
            return this.trunc(width);
        }
        return this;
    }
    APInt_ zextOrSelf(uint width) {
        if (this.BitWidth < width) {
            return this.zext(width);
        }
        return this;
    }
    APInt_ sextOrSelf(uint width) {
        if (this.BitWidth < width) {
            return this.sext(width);
        }
        return this;
    }
    bool ne(APInt_ RHS) { return !(this.Op等等(RHS)); }
    bool ult(APInt_ RHS) { return this.compare(RHS) < 0; }
    bool ult(ulong RHS) {
        // Only need to check active bits if not a single word.
        return (this.isSingleWord() || this.getActiveBits() <= 64) && this.getZExtValue() < RHS;
    }
    bool slt(APInt_ RHS) { return this.compareSigned(RHS) < 0; }
    bool slt(ulong RHS) {
        return (!this.isSingleWord() && this.getMinSignedBits() > 64) ? this.isNegative() : this.getSExtValue() < RHS;
    }
    bool ule(APInt_ RHS) { return this.compare(RHS) <= 0; }
    bool ule(ulong RHS) { return !this.ugt(RHS); }
    bool sle(APInt_ RHS) { return this.compareSigned(RHS) <= 0; }
    bool sle(ulong RHS) { return !this.sgt(RHS); }
    bool ugt(APInt_ RHS) { return !this.ule(RHS); }
    bool ugt(ulong RHS) {
        // Only need to check active bits if not a single word.
        return (!this.isSingleWord() && this.getActiveBits() > 64) || this.getZExtValue() > RHS;
    }
    bool sgt(APInt_ RHS) { return !this.sle(RHS); }
    bool sgt(long RHS) {
        return (!this.isSingleWord() && this.getMinSignedBits() > 64) ? !this.isNegative() : this.getSExtValue() > RHS;
    }
    bool uge(APInt_ RHS) { return !this.ult(RHS); }
    bool uge(ulong RHS) { return !this.ult(RHS); }
    bool sge(APInt_ RHS) { return !this.slt(RHS); }
    bool sge(long RHS) { return !this.slt(RHS); }
    void ashrSlowCase(uint ShiftAmt) {
        // Don't bother performing a no-op shift.
        if (ShiftAmt == 0) {
            return;
        }
        // Save the original sign bit for later.
        bool Negative = this.isNegative();
        // WordShift is the inter-part shift; BitShift is intra-part shift.
        uint WordShift = (cast(uint)(ShiftAmt / .APINT_BITS_PER_WORD));
        uint bitShift = (cast(uint)(ShiftAmt % .APINT_BITS_PER_WORD));
        uint WordsToMove = this.getNumWords() - WordShift;
        if (WordsToMove != 0) {
            // Sign extend the last word to fill in the unused bits.
            this.U[this.getNumWords() - 1] = .SignExtend64(this.U[this.getNumWords() - 1], (cast(uint)((bitShift - 1) % .APINT_BITS_PER_WORD)) + 1);
            // Fastpath for moving by whole words.
            if (bitShift == 0) {
                .·memmove(this.U.ptr, this.U[WordShift .. $].ptr, WordsToMove * .APINT_WORD_SIZE);
            }
            else {
                {
                    // Move the words containing significant bits.
                    for (uint i = 0; i != WordsToMove - 1; ++i) {
                        this.U[i] = (this.U[i + WordShift] >> bitShift) | (this.U[i + WordShift + 1] << (.APINT_BITS_PER_WORD - bitShift));
                    }
                }
                // Handle the last word which has no high bits to copy.
                this.U[WordsToMove - 1] = this.U[WordShift + WordsToMove - 1] >> bitShift;
                // Sign extend one more time.
                this.U[WordsToMove - 1] = .SignExtend64(this.U[WordsToMove - 1], (cast(uint)(.APINT_BITS_PER_WORD - bitShift)));
            }
        }
        // Fill in the remainder based on the original sign.
        .·memset(this.U[WordsToMove .. $].ptr, Negative ? -1 : 0, WordShift * .APINT_WORD_SIZE);
        this.clearUnusedBits();
    }
    void OrAssignSlowCase(APInt_ RHS) {
        .tcOr(this.U, RHS.U, this.getNumWords());
    }
    void XorAssignSlowCase(APInt_ RHS) {
        .tcXor(this.U, RHS.U, this.getNumWords());
    }
    bool isMaxSignedValue() {
        if (this.isSingleWord()) {
            return this.U[0] == (((cast(WordType_)(1)) << (this.BitWidth - 1)) - 1);
        }
        return !this.isNegative() && this.countTrailingOnesSlowCase() == this.BitWidth - 1;
    }
    bool isMinValue() { return this.isNullValue(); }
    bool isMinSignedValue() {
        if (this.isSingleWord()) {
            return this.U[0] == ((cast(WordType_)(1)) << (this.BitWidth - 1));
        }
        return this.isNegative() && this.countTrailingZerosSlowCase() == this.BitWidth - 1;
    }
    bool isIntN(uint N) {
        return this.getActiveBits() <= N;
    }
    bool isSignedIntN(uint N) {
        return this.getMinSignedBits() <= N;
    }
    bool isPowerOf2() {
        if (this.isSingleWord()) {
            return .isPowerOf2_64(this.U[0]);
        }
        return this.countPopulationSlowCase() == 1;
    }
    uint countPopulationSlowCase() {
        uint Count = 0;
        {
            for (uint i = 0; i < this.getNumWords(); ++i) {
                Count += .llvm_countPopulation_64(this.U[i]);
            }
        }
        return Count;
    }
    bool isSignMask() {
        return this.isMinSignedValue();
    }
    bool isSplat(uint SplatSizeInBits) {
        // We can check that all parts of an integer are equal by making use of a
        // little trick: rotate and check 如果 it's still the same value.
        return this.Op等等(this.rotl(SplatSizeInBits));
    }
    APInt_ rotl(APInt_ rotateAmt) {
        return this.rotl(.rotateModulo(this.BitWidth, rotateAmt));
    }
    APInt_ rotl(uint rotateAmt) {
        rotateAmt %= this.BitWidth;
        if (rotateAmt == 0) {
            return this;
        }
        APInt_ a = this.shl(rotateAmt);
        APInt_ b = this.lshr(this.BitWidth - rotateAmt);
        return a.Op或等(b);
    }
    APInt_ rotr(APInt_ rotateAmt) {
        return this.rotr(.rotateModulo(this.BitWidth, rotateAmt));
    }
    APInt_ rotr(uint rotateAmt) {
        rotateAmt %= this.BitWidth;
        if (rotateAmt == 0) {
            return this;
        }
        APInt_ a = this.lshr(rotateAmt);
        APInt_ b = this.shl(this.BitWidth - rotateAmt);
        return a.Op或等(b);
    }
    bool isMask(uint numBits) {
        if (this.isSingleWord()) {
            return this.U[0] == (.WORDTYPE_MAX >> (.APINT_BITS_PER_WORD - numBits));
        }
        uint Ones = this.countTrailingOnesSlowCase();
        return (numBits == Ones) && ((Ones + this.countLeadingZerosSlowCase()) == this.BitWidth);
    }
    bool isMask() {
        if (this.isSingleWord()) {
            return .isMask_64(this.U[0]);
        }
        uint Ones = this.countTrailingOnesSlowCase();
        return (Ones > 0) && ((Ones + this.countLeadingZerosSlowCase()) == this.BitWidth);
    }
    bool isShiftedMask() {
        if (this.isSingleWord()) {
            return .isShiftedMask_64(this.U[0]);
        }
        uint Ones = this.countPopulationSlowCase();
        uint LeadZ = this.countLeadingZerosSlowCase();
        return (Ones + LeadZ + this.countTrailingZeros()) == this.BitWidth;
    }
    APInt_ getHiBits(uint numBits) {
        return this.lshr(this.BitWidth - numBits);
    }
    APInt_ getLoBits(uint numBits) {
        APInt_ n = .getLowBitsSet(this.BitWidth, numBits);
        APInt_ Result = new APInt_(n);
        Result.Op且等(this);
        return Result;
    }
    void setLowBits(uint loBits) {
        return this.setBits(0, loBits);
    }
    void setBits(uint loBit, uint hiBit) {
        if (loBit == hiBit) {
            return;
        }
        if (loBit < .APINT_BITS_PER_WORD && hiBit <= .APINT_BITS_PER_WORD) {
            ulong mask = .WORDTYPE_MAX >> (.APINT_BITS_PER_WORD - (hiBit - loBit));
            mask <<= loBit;
            this.U[0] |= mask;
        }
        else {
            this.setBitsSlowCase(loBit, hiBit);
        }
    }
    APInt_ urem(APInt_ RHS) {
        if (this.isSingleWord()) {
            return new APInt_(this.BitWidth, this.U[0] % RHS.U[0]);
        }
        // Get some facts about the LHS
        uint lhsWords = .getNumWords(this.getActiveBits());
        // Get some facts about the RHS
        uint rhsBits = RHS.getActiveBits();
        uint rhsWords = .getNumWords(rhsBits);
        // Check the degenerate cases
        if (lhsWords == 0) {
            // 0 % Y ===> 0
            return new APInt_(this.BitWidth, 0);
        }
        if (rhsBits == 1) {
            // X % 1 ===> 0
            return new APInt_(this.BitWidth, 0);
        }
        if (lhsWords < rhsWords || this.ult(RHS)) {
            // X % Y ===> X, iff X < Y
            return this;
        }
        if (this.Op等等(RHS)) {
            // X % X == 0;
            return new APInt_(this.BitWidth, 0);
        }
        if (lhsWords == 1) {
            // All high words are zero, just use native remainder
            return new APInt_(this.BitWidth, this.U[0] % RHS.U[0]);
        }
        // We have to compute it the hard way. Invoke the Knuth divide algorithm.
        APInt_ Remainder = new APInt_(this.BitWidth, 0);
        ulong[] 商 = 创建数组!(ulong)();
        .divide(this.U, lhsWords, RHS.U, rhsWords, 商, Remainder.U);
        return Remainder;
    }
    ulong urem(ulong RHS) {
        if (this.isSingleWord()) {
            return this.U[0] % RHS;
        }
        // Get some facts about the LHS
        uint lhsWords = .getNumWords(this.getActiveBits());
        // Check the degenerate cases
        if (lhsWords == 0) {
            // 0 % Y ===> 0
            return 0;
        }
        if (RHS == 1) {
            // X % 1 ===> 0
            return 0;
        }
        if (this.ult(RHS)) {
            // X % Y ===> X, iff X < Y
            return this.getZExtValue();
        }
        if (this.Op等等(RHS)) {
            // X % X == 0;
            return 0;
        }
        if (lhsWords == 1) {
            // All high words are zero, just use native remainder
            return this.U[0] % RHS;
        }
        // We have to compute it the hard way. Invoke the Knuth divide algorithm.
        ulong[] Remainder = 创建数组!(ulong)();
        ulong[] 商 = 创建数组!(ulong)();
        ulong[] 除数 = [RHS];
        .divide(this.U, lhsWords, 除数, 1, 商, Remainder);
        return Remainder[0];
    }
    APInt_ shl(uint shiftAmt) {
        APInt_ R = this;
        R.Op左移等(shiftAmt);
        return R;
    }
    APInt_ shl(APInt_ ShiftAmt) {
        APInt_ R = this;
        R.Op左移等(ShiftAmt);
        return R;
    }
    APInt_ ashr(uint ShiftAmt) {
        APInt_ R = this;
        R.ashrInPlace(ShiftAmt);
        return R;
    }
    APInt_ ashr(APInt_ ShiftAmt) {
        APInt_ R = this;
        R.ashrInPlace(ShiftAmt);
        return R;
    }
    void ashrInPlace(uint ShiftAmt) {
        if (this.isSingleWord()) {
            ulong SExtVAL = .SignExtend64(this.U[0], this.BitWidth);
            if (ShiftAmt == this.BitWidth) {
                this.U[0] = SExtVAL >> (.APINT_BITS_PER_WORD - 1); // Fill with sign bit.
            }
            else {
                this.U[0] = SExtVAL >> ShiftAmt;
            }
            this.clearUnusedBits();
            return;
        }
        this.ashrSlowCase(ShiftAmt);
    }
    void ashrInPlace(APInt_ shiftAmt) {
        this.ashrInPlace((cast(uint)(shiftAmt.getLimitedValue(this.BitWidth))));
    }
    APInt_ lshr(uint shiftAmt) {
        APInt_ R = this;
        R.lshrInPlace(shiftAmt);
        return R;
    }
    APInt_ lshr(APInt_ shiftAmt) {
        APInt_ R = this;
        R.lshrInPlace(shiftAmt);
        return R;
    }
    void lshrInPlace(uint ShiftAmt) {
        if (this.isSingleWord()) {
            if (ShiftAmt == this.BitWidth) {
                this.U[0] = 0;
            }
            else {
                this.U[0] >>= ShiftAmt;
            }
            return;
        }
        this.lshrSlowCase(ShiftAmt);
    }
    void lshrInPlace(APInt_ ShiftAmt) {
        this.lshrInPlace((cast(uint)(ShiftAmt.getLimitedValue(this.BitWidth))));
    }
    APInt_ sqrt() {
        // Determine the magnitude of the value.
        uint magnitude = this.getActiveBits();
        // Use a fast table 循环 some small values. This also gets rid of some
        // rounding errors in libc sqrt 循环 small values.
        if (magnitude <= 5) {
            return new APInt_(this.BitWidth, _sqrtResults[this.U[0]]);
        }
        // Okay, all the short cuts are exhausted. We must compute it. The following
        // is a classical Babylonian method 循环 computing the square root. This code
        // was adapted to APInt_ from a wikipedia article on such computations.
        // See http://www.wikipedia.org/ and go to the page named
        // Calculate_an_integer_square_root.
        uint nbits = this.BitWidth;
        uint i = 4;
        APInt_ testy = new APInt_(this.BitWidth, 16);
        APInt_ x_old = new APInt_(this.BitWidth, 1);
        APInt_ x_new = new APInt_(this.BitWidth, 0);
        APInt_ two = new APInt_(this.BitWidth, 2);
        // Select a good starting value using binary logarithms.
        for (;; i += 2, testy = testy.shl(2)) {
            if (i >= nbits || this.ule(testy)) {
                x_old = x_old.shl(i / 2);
                break;
            }
        }
        // Use the Babylonian method to arrive at the integer square root:
        for (;;) {
            x_new = (this.udiv(x_old).Op加等(x_old)).udiv(two);
            if (x_old.ule(x_new)) {
                break;
            }
            x_old = x_new;
        }
        // Make sure we 返回 the closest approximation
        // NOTE: The rounding calculation below is correct. It will produce an
        // off-by-one discrepancy with results from pari/gp. That discrepancy has been
        // determined to be a rounding issue with pari/gp as it begins to use a
        // floating point representation after 192 bits. There are no discrepancies
        // between 本体 algorithm and pari/gp 循环 bit widths < 192 bits.
        APInt_ square = new APInt_(x_old.Op乘(x_old));
        APInt_ nextSquare = new APInt_((.Op_APInt_加_2(x_old, 1)).Op乘(.Op_APInt_加_2(x_old, 1)));
        if (this.ult(square)) {
            return x_old;
        }
        APInt_ midpoint = new APInt_((nextSquare.Op减等(square)).udiv(two));
        APInt_ offset = new APInt_(.Op_APInt_减(this, square));
        if (offset.ult(midpoint)) {
            return x_old;
        }
        return x_old.Op加等(1);
    }
    APInt_ multiplicativeInverse(APInt_ modulo) {
        // Using the properties listed at the following web page (accessed 06/21/08):
        //   http://www.numbertheory.org/php/euclid.html
        // (especially the properties numbered 3, 4 and 9) it can be proved that
        // BitWidth bits suffice 循环 all the computations in the algorithm implemented
        // below. More precisely, 本体 number of bits suffice 如果 the multiplicative
        // inverse exists, but may not suffice 循环 the general extended Euclidean
        // algorithm.
        APInt_[2] r = [modulo, this];
        APInt_[2] t = [new APInt_(this.BitWidth, 0), new APInt_(this.BitWidth, 1)];
        APInt_ q = new APInt_(this.BitWidth, 0);
        uint i;
        for (i = 0; !(r[i ^ 1]).Op等等(0); i ^= 1) {
            // An overview of the math without the confusing bit-flipping:
            // q = r[i-2] / r[i-1]
            // r[i] = r[i-2] % r[i-1]
            // t[i] = t[i-2] - t[i-1] * q
            .udivrem_2(r[i], r[i ^ 1], q, r[i]);
            t[i].Op减等(.Op_APInt_乘(t[i ^ 1], q));
        }
        // If 本体 APInt_ and the modulo are not coprime, there is no multiplicative
        // inverse, so 返回 0. We check 本体 by looking at the next-to-last
        // remainder, which is the gcd(*本体,modulo) as calculated by the Euclidean
        // algorithm.
        if (!r[i].Op等等(1)) {
            return new APInt_(this.BitWidth, 0);
        }
        // The next-to-last t is the multiplicative inverse.  However, we are
        // interested in a positive inverse. Calculate a positive one from a negative
        // one 如果 necessary. A simple addition of the modulo suffices because
        // abs(t[i]) is known to be less than *本体/2 (see the link above).
        if (t[i].isNegative()) {
            (t[i]).Op加等(modulo);
        }
        return t[i];
    }
    APInt_ms magic() {
        APInt_ d = this;
        uint p;
        APInt_ ad;
        APInt_ anc;
        APInt_ delta;
        APInt_ q1;
        APInt_ r1;
        APInt_ q2;
        APInt_ r2;
        APInt_ t;
        APInt_ signedMin = .getSignedMinValue(d.getBitWidth());
        APInt_ms mag;
        ad = d.abs();
        t = .Op_APInt_加(signedMin, (d.lshr(d.getBitWidth() - 1)));
        anc = .Op_APInt_减(.Op_APInt_减_2(t, 1), t.urem(ad)); // absolute value of nc
        p = d.getBitWidth() - 1; // initialize p
        q1 = signedMin.udiv(anc); // initialize q1 = 2p/abs(nc)
        r1 = .Op_APInt_减(signedMin, .Op_APInt_乘(q1, anc)); // initialize r1 = rem(2p,abs(nc))
        q2 = signedMin.udiv(ad); // initialize q2 = 2p/abs(d)
        r2 = .Op_APInt_减(signedMin, .Op_APInt_乘(q2, ad));
        bool 第一层 = false;
        while(!第一层 || q1.ult(delta) || (q1.Op等等(delta) && r1.Op等等(0))) {
            第一层 = true;
            p = p + 1;
            q1.Op左移等(1); // update q1 = 2p/abs(nc)
            r1.Op左移等(1); // update r1 = rem(2p/abs(nc))                
            if (r1.uge(anc)) { // must be 正整数32 comparison
                q1.Op加等(1);
                r1.Op减等(anc);
            }
            q2.Op左移等(1); // update q2 = 2p/abs(d)
            r2.Op左移等(1); // update r2 = rem(2p/abs(d))
            if (r2.uge(ad)) { // must be 正整数32 comparison
                q2.Op加等(1);
                r2.Op减等(ad);
            }
            delta = .Op_APInt_减(ad, r2);
        }
        mag.m = .Op_APInt_加_2(q2, 1);
        if (d.isNegative()) {
            mag.m = mag.m.Op负();
        } // resulting magic number
        mag.s = p - d.getBitWidth(); // resulting shift
        return mag;
    }
    APInt_mu magicu(uint LeadingZeros) {
        APInt_ d = this;
        uint p;
        APInt_ nc;
        APInt_ delta;
        APInt_ q1;
        APInt_ r1;
        APInt_ q2;
        APInt_ r2;
        APInt_mu magu;
        magu.a = false; // initialize "add" indicator
        APInt_ allOnes = .getAllOnesValue(d.getBitWidth()).lshr(LeadingZeros);
        APInt_ signedMin = .getSignedMinValue(d.getBitWidth());
        APInt_ signedMax = .getSignedMaxValue(d.getBitWidth());
        nc = .Op_APInt_减(allOnes, (.Op_APInt_减(allOnes, d)).urem(d));
        p = d.getBitWidth() - 1; // initialize p
        q1 = signedMin.udiv(nc); // initialize q1 = 2p/nc
        r1 = .Op_APInt_减(signedMin, .Op_APInt_乘(q1, nc)); // initialize r1 = rem(2p,nc)
        q2 = signedMax.udiv(d); // initialize q2 = (2p-1)/d
        r2 = .Op_APInt_减(signedMax, .Op_APInt_乘(q2, d)); // initialize r2 = rem((2p-1),d)
        bool 第一层 = false;
        while(!第一层 || p < d.getBitWidth() * 2 && (q1.ult(delta) || (q1.Op等等(delta) && r1.Op等等(0)))) {
            第一层 = true;
            p = p + 1;
            if (r1.uge(.Op_APInt_减(nc, r1))) {
                q1 = .Op_APInt_加_2(.Op_APInt_加(q1, q1), 1); // update q1
                r1 = .Op_APInt_减(.Op_APInt_加(r1, r1), nc); // update r1
            }
            else {
                q1 = .Op_APInt_加(q1, q1); // update q1
                r1 = .Op_APInt_加(r1, r1); // update r1
            }
            if ((.Op_APInt_加_2(r2, 1)).uge(.Op_APInt_减(d, r2))) {
                if (q2.uge(signedMax)) {
                    magu.a = true;
                }
                q2 = .Op_APInt_加_2(.Op_APInt_加(q2, q2), 1); // update q2
                r2 = .Op_APInt_减(.Op_APInt_加_2(.Op_APInt_加(r2, r2), 1), d); // update r2
            }
            else {
                if (q2.uge(signedMin)) {
                    magu.a = true;
                }
                q2 = .Op_APInt_加(q2, q2); // update q2
                r2 = .Op_APInt_加_2(.Op_APInt_加(r2, r2), 1); // update r2
            }
            delta = .Op_APInt_减(.Op_APInt_减_2(d, 1), r2);
        }
        magu.m = .Op_APInt_加_2(q2, 1); // resulting magic number
        magu.s = p - d.getBitWidth(); // resulting shift
        return magu;
    }
    APInt_ sdiv(APInt_ RHS) {
        if (this.isNegative()) {
            if (RHS.isNegative()) {
                return ((this).Op负()).udiv(RHS.Op负());
            }
            return (((this).Op负()).udiv(RHS)).Op负();
        }
        if (RHS.isNegative()) {
            return (this.udiv(RHS.Op负())).Op负();
        }
        return this.udiv(RHS);
    }
    APInt_ srem(APInt_ RHS) {
        if (this.isNegative()) {
            if (RHS.isNegative()) {
                return (((this).Op负()).urem(RHS.Op负())).Op负();
            }
            return (((this).Op负()).urem(RHS)).Op负();
        }
        if (RHS.isNegative()) {
            return this.urem(RHS.Op负());
        }
        return this.urem(RHS);
    }
    ulong srem(long RHS) {
        if (this.isNegative()) {
            if (RHS < 0) {
                return -(((this).Op负()).urem(-RHS));
            }
            return -(((this).Op负()).urem(RHS));
        }
        if (RHS < 0) {
            return this.urem(-RHS);
        }
        return this.urem(RHS);
    }
    APInt_ sadd_ov(APInt_ RHS, ref bool Overflow) {
        APInt_ Res = .Op_APInt_加(this, RHS);
        Overflow = this.isNonNegative() == RHS.isNonNegative() && Res.isNonNegative() != this.isNonNegative();
        return Res;
    }
    APInt_ uadd_ov(APInt_ RHS, ref bool Overflow) {
        APInt_ Res = .Op_APInt_加(this, RHS);
        Overflow = Res.ult(RHS);
        return Res;
    }
    APInt_ ssub_ov(APInt_ RHS, ref bool Overflow) {
        APInt_ Res = .Op_APInt_减(this, RHS);
        Overflow = this.isNonNegative() != RHS.isNonNegative() && Res.isNonNegative() != this.isNonNegative();
        return Res;
    }
    APInt_ usub_ov(APInt_ RHS, ref bool Overflow) {
        APInt_ Res = .Op_APInt_减(this, RHS);
        Overflow = Res.ugt(this);
        return Res;
    }
    APInt_ sdiv_ov(APInt_ RHS, ref bool Overflow) {
        // MININT/-1  -.  overflow.
        Overflow = this.isMinSignedValue() && RHS.isAllOnesValue();
        return this.sdiv(RHS);
    }
    APInt_ smul_ov(APInt_ RHS, ref bool Overflow) {
        APInt_ Res = .Op_APInt_乘(this, RHS);
        if (!this.Op等等(0) && !RHS.Op等等(0)) {
            Overflow = !Res.sdiv(RHS).Op等等(this) || !Res.sdiv(this).Op等等(RHS);
        }
        else {
            Overflow = false;
        }
        return Res;
    }
    APInt_ umul_ov(APInt_ RHS, ref bool Overflow) {
        if (this.countLeadingZeros() + RHS.countLeadingZeros() + 2 <= this.BitWidth) {
            Overflow = true;
            return .Op_APInt_乘(this, RHS);
        }
        APInt_ Res = .Op_APInt_乘(this.lshr(1), RHS);
        Overflow = Res.isNegative();
        Res.Op左移等(1);
        if ((this).Op索引访问(0)) {
            Res.Op加等(RHS);
            if (Res.ult(RHS)) {
                Overflow = true;
            }
        }
        return Res;
    }
    APInt_ sshl_ov(APInt_ ShAmt, ref bool Overflow) {
        Overflow = ShAmt.uge(this.getBitWidth());
        if (Overflow) {
            return new APInt_(this.BitWidth, 0);
        }
        if (this.isNonNegative()) // Don't allow sign change.
         {
            Overflow = ShAmt.uge(this.countLeadingZeros());
        }
        else {
            Overflow = ShAmt.uge(this.countLeadingOnes());
        }
        APInt_ b = this;
        return b.Op左移等(ShAmt);
    }
    APInt_ ushl_ov(APInt_ ShAmt, ref bool Overflow) {
        Overflow = ShAmt.uge(this.getBitWidth());
        if (Overflow) {
            return new APInt_(this.BitWidth, 0);
        }
        Overflow = ShAmt.ugt(this.countLeadingZeros());
        return this.Op左移(ShAmt);
    }
    APInt_ sadd_sat(APInt_ RHS) {
        bool Overflow = false;
        APInt_ Res = this.sadd_ov(RHS, Overflow);
        if (!Overflow) {
            return Res;
        }
        return this.isNegative() ? .getSignedMinValue(this.BitWidth) : .getSignedMaxValue(this.BitWidth);
    }
    APInt_ uadd_sat(APInt_ RHS) {
        bool Overflow = false;
        APInt_ Res = this.uadd_ov(RHS, Overflow);
        if (!Overflow) {
            return Res;
        }
        return .getMaxValue(this.BitWidth);
    }
    APInt_ ssub_sat(APInt_ RHS) {
        bool Overflow = false;
        APInt_ Res = this.ssub_ov(RHS, Overflow);
        if (!Overflow) {
            return Res;
        }
        return this.isNegative() ? .getSignedMinValue(this.BitWidth) : .getSignedMaxValue(this.BitWidth);
    }
    APInt_ usub_sat(APInt_ RHS) {
        bool Overflow = false;
        APInt_ Res = this.usub_ov(RHS, Overflow);
        if (!Overflow) {
            return Res;
        }
        return new APInt_(this.BitWidth, 0);
    }
    APInt_ smul_sat(APInt_ RHS) {
        bool Overflow = false;
        APInt_ Res = this.smul_ov(RHS, Overflow);
        if (!Overflow) {
            return Res;
        }
        // The result is negative 如果 one and only one of inputs is negative.
        bool ResIsNegative = ((this.isNegative() ^ RHS.isNegative()) != 0);
        return ResIsNegative ? .getSignedMinValue(this.BitWidth) : .getSignedMaxValue(this.BitWidth);
    }
    APInt_ umul_sat(APInt_ RHS) {
        bool Overflow = false;
        APInt_ Res = this.umul_ov(RHS, Overflow);
        if (!Overflow) {
            return Res;
        }
        return .getMaxValue(this.BitWidth);
    }
    APInt_ sshl_sat(APInt_ RHS) {
        bool Overflow = false;
        APInt_ Res = this.sshl_ov(RHS, Overflow);
        if (!Overflow) {
            return Res;
        }
        return this.isNegative() ? .getSignedMinValue(this.BitWidth) : .getSignedMaxValue(this.BitWidth);
    }
    APInt_ ushl_sat(APInt_ RHS) {
        bool Overflow = false;
        APInt_ Res = this.ushl_ov(RHS, Overflow);
        if (!Overflow) {
            return Res;
        }
        return .getMaxValue(this.BitWidth);
    }
    APInt_ reverseBits() {
        switch (this.BitWidth) {
            case 64: {
                return new APInt_(this.BitWidth, .llvm_reverseBits!(ulong)(this.U));
            }
            case 32: {
                return new APInt_(this.BitWidth, (cast(ulong[])(.llvm_reverseBits!(uint)((cast(uint[])(this.U))))));
            }
            case 16: {
                return new APInt_(this.BitWidth, (cast(ulong[])(.llvm_reverseBits!(ushort)((cast(ushort[])(this.U))))));
            }
            case 8: {
                return new APInt_(this.BitWidth, (cast(ulong[])(.llvm_reverseBits!(ubyte)((cast(ubyte[])(this.U))))));
            }
            default: {
                break;
            }
        }
        APInt_ Val = new APInt_(this);
        APInt_ Reversed = new APInt_(this.BitWidth, 0);
        uint S = this.BitWidth;
        for (; !Val.Op等等(0); Val.lshrInPlace(1)) {
            Reversed.Op左移等(1);
            Reversed.Op或等(Val.Op索引访问(0) ? 1 : 0);
            --S;
        }
        Reversed.Op左移等(S);
        return Reversed;
    }
}
/// Magic data for optimising signed division by a constant.
struct APInt_ms {
    APInt_ m; ///< magic number
    uint s; ///< shift amount
}
/// Magic data for optimising unsigned division by a constant.
struct APInt_mu {
    APInt_ m; ///< magic number
    bool a; ///< add indicator
    uint s; ///< shift amount
}
T[] llvm_reverseBits(T)(T[] Val) {
    ubyte[] in1 = 创建数组!(ubyte)(); //[sizeof(Val)];
    in1.length = Val.sizeof;
    ubyte[] out2 = 创建数组!(ubyte)(); //[sizeof(Val)];
    out2.length = Val.sizeof;
    .·memcpy(in1.ptr, Val.ptr, Val.sizeof);
    {
        for (int i = 0; i < Val.sizeof; ++i) {
            out2[(Val.sizeof - i) - 1] = BitReverseTable256[in1[i]];
        }
    }
    .·memcpy(Val.ptr, out2.ptr, Val.sizeof);
    return Val;
}
ubyte Log2_64(ulong Value) {
    return (cast(ubyte)(63 - (cast(ubyte)(.llvm_countLeadingZeros_64(Value)))));
}
ushort ByteSwap_16(ushort value) {
    ushort Hi = (cast(ushort)(value << 8));
    ushort Lo = value >> 8;
    return Hi | Lo;
}
uint ByteSwap_32(uint value) {
    uint Byte0 = value & 255;
    uint Byte1 = value & 65280;
    uint Byte2 = value & 16711680;
    uint Byte3 = value & 4278190080;
    return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
}
ulong ByteSwap_64(ulong value) {
    ulong Hi = (cast(ulong)(.ByteSwap_32((cast(uint)(value)))));
    uint Lo = .ByteSwap_32((cast(uint)(value >> 32)));
    return (Hi << 32) | Lo;
}
uint llvm_countPopulation_64(ulong Value) {
    ulong v = Value;
    v = v - ((v >> 1) & 6148914691236517205uL);
    v = (v & 3689348814741910323uL) + ((v >> 2) & 3689348814741910323uL);
    v = (v + (v >> 4)) & 1085102592571150095uL;
    return (cast(uint)((cast(ulong)(v * 72340172838076673uL)) >> 56));
}
uint llvm_countLeadingZeros_64(ulong Val) {
    if (Val == 0) {
        return 64;
    }
    uint ZeroBits = 0;
    {
        for (ulong Shift = 64 >> 1; Shift != 0; Shift >>= 1) {
            ulong Tmp = Val >> Shift;
            if (Tmp != 0) {
                Val = Tmp;
            }
            else {
                ZeroBits |= (cast(uint)(Shift));
            }
        }
    }
    return ZeroBits;
}
uint llvm_countLeadingZeros_32(uint Val) {
    if (Val == 0) {
        return 32;
    }
    uint ZeroBits = 0;
    {
        for (ulong Shift = 32 >> 1; Shift != 0; Shift >>= 1) {
            uint Tmp = Val >> Shift;
            if (Tmp != 0) {
                Val = Tmp;
            }
            else {
                ZeroBits |= (cast(uint)(Shift));
            }
        }
    }
    return ZeroBits;
}
uint llvm_countTrailingZeros_64(ulong Val) {
    if (Val == 0) {
        return 64;
    }
    ulong ZeroBits = 0;
    ulong Shift = 64 >> 1;
    ulong Mask = .UINT64_MAX >> Shift;
    while(Shift != 0) {
        if ((Val & Mask) == 0) {
            Val >>= Shift;
            ZeroBits |= Shift;
        }
        Shift >>= 1;
        Mask >>= Shift;
    }
    return (cast(uint)(ZeroBits));
}
uint llvm_countTrailingZeros_32(uint Val) {
    if (Val == 0) {
        return 64;
    }
    if ((Val & 1) != 0) {
        return 0;
    }
    uint ZeroBits = 0;
    uint Shift = 32 >> 1;
    uint Mask = .UINT32_MAX >> Shift;
    while(Shift != 0) {
        if ((Val & Mask) == 0) {
            Val >>= Shift;
            ZeroBits |= Shift;
        }
        Shift >>= 1;
        Mask >>= Shift;
    }
    return (cast(uint)(ZeroBits));
}
uint llvm_countLeadingOnes(ulong V) {
    return .llvm_countLeadingZeros_64(~V);
}
uint llvm_countLeadingOnes_32(uint V) {
    return .llvm_countLeadingZeros_32(~V);
}
/// Get a value with low bits set
///
/// Constructs an APInt value that has the bottom loBitsSet bits set.
///
/// \param numBits the bitwidth of the result
/// \param loBitsSet the number of low-order bits set in the result.
APInt_ getLowBitsSet(uint numBits, uint loBitsSet) {
    APInt_ Res = new APInt_(numBits, 0);
    Res.setLowBits(loBitsSet);
    return Res;
}
ulong[] getClearedMemory(uint numWords) {
    ulong[] 结果 = 创建数组!(ulong)();
    结果.length = numWords;
    return 结果;
}
/// Return a value containing V broadcasted over NewLen bits.
APInt_ getSplat(uint NewLen, APInt_ V) {
    APInt_ Val = V.zextOrSelf(NewLen);
    {
        for (uint I = V.getBitWidth(); I < NewLen; I <<= 1) {
            Val.Op或等(Val.shl(I));
        }
    }
    return Val;
}
APInt_ getZero(uint numBits) {
    return new APInt_(numBits, 0);
}
APInt_ getNullVale(uint numBits) {
    return .getZero(numBits);
}
APInt_ getZeroWidth() {
    return .getZero(0);
}
APInt_ getMaxValue(uint numBits) {
    return .getAllOnesValue(numBits);
}
/// Gets maximum signed value of APInt_ for a specific bit width.
APInt_ getSignedMaxValue(uint numBits) {
    APInt_ API = .getAllOnesValue(numBits);
    API.clearBit(numBits - 1);
    return API;
}
/// Gets minimum 正整数32 value of APInt_ for a specific bit width.
APInt_ getMinValue(uint numBits) { return new APInt_(numBits, 0); }
/// Gets minimum signed value of APInt_ for a specific bit width.
APInt_ getSignedMinValue(uint numBits) {
    APInt_ API = new APInt_(numBits, 0);
    API.setBit(numBits - 1);
    return API;
}
/// Get the SignMask for a specific bit width.
///
/// This is just a wrapper function of getSignedMinValue(), and it helps code
/// readability when we want to get a SignMask.
APInt_ getSignMask(uint bitWidth) {
    return .getSignedMinValue(bitWidth);
}
APInt_ getAllOnesValue(uint numBits) {
    return new APInt_(numBits, .WORDTYPE_MAX, true);
}
ulong whichWord(uint bitPosition) {
    return bitPosition / .APINT_BITS_PER_WORD;
}
ulong whichBit(uint bitPosition) {
    return bitPosition % .APINT_BITS_PER_WORD;
}
ulong maskBit(uint bitPosition) {
    return 1uL << .whichBit(bitPosition);
}
ulong SignExtend64(ulong X, uint B) {
    return (cast(ulong)(X << (64 - B))) >> (64 - B);
}
ulong lowBitMask(uint bits) {
    return (~(cast(WordType_)(0))) >> (.APINT_BITS_PER_WORD - bits);
}
ulong lowHalf(ulong part) {
    return part & .lowBitMask((cast(uint)(.APINT_BITS_PER_WORD / 2)));
}
ulong highHalf(ulong part) {
    return part >> (.APINT_BITS_PER_WORD / 2);
}
void tcComplement(ref ulong[] dst, uint parts) {
    {
        for (int i = 0; i < parts; ++i) {
            dst[i] = ~dst[i];
        }
    }
}
void KnuthDiv(ref uint[] u, ref uint[] v, ref uint[] q, ref uint[] r, uint m, uint n) {
    ulong b = (cast(ulong)(1)) << 32;
    uint shift = .llvm_countLeadingZeros_32(v[n - 1]);
    uint v_carry = 0;
    uint u_carry = 0;
    if (shift != 0) {
        {
            for (int i = 0; i < m + n; ++i) {
                uint u_tmp = u[i] >> (32 - shift);
                u[i] = (u[i] << shift) | u_carry;
                u_carry = u_tmp;
            }
        }
        {
            for (int i = 0; i < n; ++i) {
                uint v_tmp = v[i] >> (32 - shift);
                v[i] = (v[i] << shift) | v_carry;
                v_carry = v_tmp;
            }
        }
    }
    u[m + n] = u_carry;
    uint j = m;
    while(true) {
        ulong dividend = .Make_64(u[j + n], u[j + n - 1]);
        ulong qp = dividend / v[n - 1];
        ulong rp = dividend % v[n - 1];
        if (qp == b || qp * v[n - 2] > b * rp + u[j + n - 2]) {
            --qp;
            rp += v[n - 1];
            if (rp < b && (qp == b || qp * v[n - 2] > b * rp + u[j + n - 2])) {
                --qp;
            }
        }
        long borrow = 0;
        {
            for (uint i = 0; i < n; ++i) {
                ulong p = (cast(ulong)(qp)) * (cast(ulong)(v[i]));
                long subres = (cast(long)(u[j + i])) - borrow - .Lo_32(p);
                u[j + i] = .Lo_32(subres);
                borrow = .Hi_32(p) - .Hi_32(subres);
            }
        }
        bool isNeg = u[j + n] < borrow;
        u[j + n] -= .Lo_32(borrow);
        q[j] = .Lo_32(qp);
        if (isNeg) {
            --q[j];
            int carry = 0;
            {
                for (uint i = 0; i < n; ++i) {
                    uint limit = (cast(uint)(最小(u[j + i], v[i])));
                    u[j + i] += v[i] + carry;
                    if (u[j + i] < limit || (carry != 0 && u[j + i] == limit)) {
                        carry = 1;
                    }
                    else {
                        carry = 0;
                    }
                }
            }
            u[j + n] += carry;
        }
        if (--j < 0) {
            break;
        }
    }
    if (r !is ··null!(uint[])) {
        if (shift != 0) {
            uint carry = 0;
            {
                for (int i = n - 1; i >= 0; --i) {
                    r[i] = (u[i] >> shift) | carry;
                    carry = u[i] << (32 - shift);
                }
            }
        }
        else {
            {
                for (int i = n - 1; i >= 0; --i) {
                    r[i] = u[i];
                }
            }
        }
    }
}
uint Hi_32(ulong Value) {
    return (cast(uint)(Value >> 32));
}
uint Lo_32(ulong Value) {
    return (cast(uint)(Value));
}
ulong Make_64(uint High, uint Low) {
    return (cast(ulong)(((cast(ulong)(High)) << 32) | (cast(ulong)(Low))));
}
ulong PowerOf2Ceil(ulong A) {
    if (A == 0) {
        return 0;
    }
    return .NextPowerOf2(A - 1);
}
ulong NextPowerOf2(ulong A) {
    A |= (A >> 1);
    A |= (A >> 2);
    A |= (A >> 4);
    A |= (A >> 8);
    A |= (A >> 16);
    A |= (A >> 32);
    return A + 1;
}
uint getDigit(dchar ch, ubyte radix) {
    uint r;
    if (radix == 16 || radix == 36) {
        r = ch - 字符_.减号;
        if (r <= 9) {
            return r;
        }
        r = ch - 字符_.A;
        if (r <= radix - 11) {
            return r + 10;
        }
        radix = 10;
    }
    r = ch - 字符_.数_0;
    if (r < radix) {
        return r;
    }
    return -1u;
}
ulong findLastSet(ulong n) {
    if (n == 0) {
        return 64;
    }
    return 63 - .llvm_countLeadingZeros_64(n);
}
ulong findFirstSet(ulong Val) {
    if (Val == 0) {
        return 64;
    }
    return .llvm_countTrailingZeros_64(Val);
}
ulong partMSB(ulong n) {
    return .findLastSet(n);
}
ulong partLSB(ulong n) {
    return .findFirstSet(n);
}
uint tcLSB(ulong[] parts, uint n) {
    {
        for (uint i = 0; i < n; ++i) {
            if (parts[i] != 0) {
                ulong lsb = .partLSB(parts[i]);
                return (cast(uint)(lsb + i * .APINT_BITS_PER_WORD));
            }
        }
    }
    return -1;
}
bool tcIsZero(ulong[] src, uint parts) {
    {
        for (uint i = 0; i < parts; ++i) {
            if (src[i] != 0) {
                return false;
            }
        }
    }
    return true;
}
uint tcMSB(ulong[] parts, uint n) {
    while(n != 0) {
        --n;
        if (parts[n] != 0) {
            ulong msb = .partMSB(parts[n]);
            return (cast(uint)(msb + n * .APINT_BITS_PER_WORD));
        }
    }
    return -1;
}
bool tcExtractBit(ref ulong[] parts, uint bit) {
    return (parts[.whichWord(bit)] & .maskBit(bit)) != 0;
}
void tcSetLeastSignificantBits(ref ulong[] dst, uint parts, uint bits) {
    uint i = 0;
    while(bits > .APINT_BITS_PER_WORD) {
        dst[++i] = ~(cast(WordType_)(0));
        bits -= (cast(uint)(.APINT_BITS_PER_WORD));
    }
    if (bits != 0) {
        dst[++i] = ~(cast(WordType_)(0)) >> (.APINT_BITS_PER_WORD - bits);
    }
    while(i < parts) {
        dst[++i] = 0;
    }
}
void tcExtract(ref ulong[] dst, uint dstCount, ulong[] src, uint srcBits, uint srcLSB) {
    uint dstParts = (cast(uint)((srcBits + .APINT_BITS_PER_WORD - 1) / .APINT_BITS_PER_WORD));
    uint firstSrcPart = (cast(uint)(srcLSB / .APINT_BITS_PER_WORD));
    .tcAssign(dst, src[firstSrcPart .. $], dstParts);
    uint shift = (cast(uint)(srcLSB % .APINT_BITS_PER_WORD));
    .tcShiftRight(dst, dstParts, shift);
    /* We now have (dstParts * APINT_BITS_PER_WORD - shift) bits from SRC
    in DST.  If this is less that srcBits, append the rest, else
    clear the high bits.  */
    uint n = (cast(uint)(dstParts * .APINT_BITS_PER_WORD - shift));
    if (n < srcBits) {
        ulong mask = .lowBitMask(srcBits - n);
        dst[dstParts - 1] |= ((src[firstSrcPart + dstParts] & mask) << n % .APINT_BITS_PER_WORD);
    }
    else if (n > srcBits) {
        if ((srcBits % .APINT_BITS_PER_WORD) != 0) {
            dst[dstParts - 1] &= .lowBitMask((cast(uint)(srcBits % .APINT_BITS_PER_WORD)));
        }
    }
    /* Clear high parts.  */
    while(dstParts < dstCount) {
        dst[++dstParts] = 0;
    }
}
void tcSet(ref ulong[] dst, ulong part, uint parts) {
    dst[0] = part;
    {
        for (int i = 0; i < parts; ++i) {
            dst[i] = 0;
        }
    }
}
void tcSetBit(ref ulong[] parts, uint bit) {
    parts[.whichWord(bit)] |= .maskBit(bit);
}
void tcAnd(ref ulong[] dst, ulong[] rhs, uint parts) {
    {
        for (uint i = 0; i < parts; ++i) {
            dst[i] &= rhs[i];
        }
    }
}
/* Bitwise inclusive or of two bignums.  */
void tcOr(ulong[] dst, ulong[] rhs, uint parts) {
    {
        for (uint i = 0; i < parts; ++i) {
            dst[i] |= rhs[i];
        }
    }
}
/* Bitwise exclusive or of two bignums.  */
void tcXor(ulong[] dst, ulong[] rhs, uint parts) {
    {
        for (uint i = 0; i < parts; ++i) {
            dst[i] ^= rhs[i];
        }
    }
}
ulong tcSubtract(ref ulong[] dst, ulong[] rhs, ulong c, uint parts) {
    {
        for (uint i = 0; i < parts; ++i) {
            ulong l = dst[i];
            if (c != 0) {
                dst[i] -= rhs[i] + 1;
                c = (dst[i] >= l) ? 1 : 0;
            }
            else {
                dst[i] -= rhs[i];
                c = (dst[i] > l) ? 1 : 0;
            }
        }
    }
    return c;
}
/// This function subtracts a single "word" (64-bit word), src, from
/// the multi-word integer array, dst[], propagating the borrowed 1 value until
/// no further borrowing is needed or it runs out of "words" in dst.  The result
/// is 1 如果 "borrowing" exhausted the digits in dst, or 0 如果 dst was not
/// exhausted. In other words, 如果 src > dst then 本体 function returns 1,
/// otherwise 0.
/// @returns the borrow out of the subtraction
ulong tcSubtractPart(ulong[] dst, ulong src, uint parts) {
    {
        for (uint i = 0; i < parts; ++i) {
            ulong Dst = dst[i];
            dst[i] -= src;
            if (src <= Dst) {
                return // No need to borrow so exit early.
                 0;
            } // No need to borrow so exit early.
            src = 1; // We have to "borrow 1" from next "word"
        }
    }
    return 1;
}
void tcClearBit(ulong[] parts, uint bit) {
    parts[.whichWord(bit)] &= ~.maskBit(bit);
}
void tcAssign(ref ulong[] dst, ulong[] src, uint parts) {
    {
        for (uint i = 0; i < parts; ++i) {
            dst[i] = src[i];
        }
    }
}
int tcAddPart(ref ulong[] dst, ulong src, uint parts) {
    {
        for (int i = 0; i < parts; ++i) {
            dst[i] += src;
            if (dst[i] >= src) {
                return 0;
            }
            src = 1;
        }
    }
    return 1;
}
int tcIncrement(ref ulong[] dst, uint parts) {
    return .tcAddPart(dst, 1, parts);
}
ulong tcDecrement(ref ulong[] dst, uint parts) {
    return .tcSubtractPart(dst, 1, parts);
}
void tcShiftLeft(ref ulong[] Dst, uint Words, uint Count) {
    if (Count == 0) {
        return;
    }
    uint WordShift = (cast(uint)(最小(Count / .APINT_BITS_PER_WORD, Words)));
    uint BitShift = (cast(uint)(Count % .APINT_BITS_PER_WORD));
    if (BitShift == 0) {
        .·memmove(Dst[WordShift .. $].ptr, Dst.ptr, (Words - WordShift) * .APINT_WORD_SIZE);
    }
    else {
        while(Words > WordShift) {
            --Words;
            Dst[Words] = Dst[Words - WordShift] << BitShift;
            if (Words > WordShift) {
                Dst[Words] |= Dst[Words - WordShift - 1] >> (.APINT_BITS_PER_WORD - BitShift);
            }
        }
    }
    .·memset(Dst.ptr, 0, WordShift * .APINT_WORD_SIZE);
}
void tcShiftRight(ref ulong[] Dst, uint Words, uint Count) {
    if (Count == 0) {
        return;
    }
    uint WordShift = (cast(uint)(最小(Count / .APINT_BITS_PER_WORD, Words)));
    uint BitShift = (cast(uint)(Count % .APINT_BITS_PER_WORD));
    uint WordsToMove = (cast(uint)(Words - WordShift));
    if (BitShift == 0) {
        .·memmove(Dst.ptr, Dst[WordShift .. $].ptr, WordsToMove * .APINT_WORD_SIZE);
    }
    else {
        {
            for (int i = 0; i != WordsToMove; ++i) {
                Dst[i] = Dst[i + WordShift] >> BitShift;
                if (i + 1 != WordsToMove) {
                    Dst[i] |= Dst[i + WordShift + 1] << (.APINT_BITS_PER_WORD - BitShift);
                }
            }
        }
    }
    // Fill in the remainder with 0s.
    .·memset(Dst[WordsToMove .. $].ptr, 0, WordShift * .APINT_WORD_SIZE);
}
/// DST = LHS * RHS, where DST has width the sum of the widths of the
/// operands. No overflow occurs. DST must be disjoint from both operands.
void tcFullMultiply(ref ulong[] dst, ulong[] lhs, ulong[] rhs, uint lhsParts, uint rhsParts) {
    // Put the narrower number on the LHS for less loops below.
    if (lhsParts > rhsParts) {
        .tcFullMultiply(dst, rhs, lhs, rhsParts, lhsParts);
        return;
    }
    .tcSet(dst, 0, rhsParts);
    {
        for (int i = 0; i < lhsParts; ++i) {
            ulong[] dst2 = dst[i .. $];
            .tcMultiplyPart(dst2, rhs, lhs[i], 0, rhsParts, rhsParts + 1, true);
        }
    }
}
int tcMultiply(ref ulong[] dst, ulong[] lhs, ulong[] rhs, uint parts) {
    int overflow = 0;
    .tcSet(dst, 0, parts);
    {
        for (int i = 0; i < parts; ++i) {
            ulong[] a = dst[i .. $];
            overflow |= .tcMultiplyPart(a, lhs, rhs[i], 0, parts, parts - i, true);
        }
    }
    return overflow;
}
uint tcMultiplyPart(ref ulong[] dst, ulong[] src, ulong multiplier, ulong carry, uint srcParts, uint dstParts, bool add) {
    uint n = (cast(uint)(最小(dstParts, srcParts)));
    {
        for (uint i = 0; i < n; ++i) {
            ulong srcPart = src[i];
            ulong low = 0;
            ulong mid = 0;
            ulong high = 0;
            if (multiplier == 0 || srcPart == 0) {
                low = carry;
                high = 0;
            }
            else {
                low = .lowHalf(srcPart) * .lowHalf(multiplier);
                high = .highHalf(srcPart) * .highHalf(multiplier);
                mid = .lowHalf(srcPart) * .highHalf(multiplier);
                high += .highHalf(mid);
                mid <<= (.APINT_BITS_PER_WORD / 2);
                if (low + mid < low) {
                    ++high;
                }
                low += mid;
                mid = .highHalf(srcPart) * .lowHalf(multiplier);
                high += .highHalf(mid);
                mid <<= (.APINT_BITS_PER_WORD / 2);
                if (low + mid < low) {
                    ++high;
                }
                low += mid;
                if (low + carry < low) {
                    ++high;
                }
                low += carry;
            }
            if (add) {
                if (low + dst[i] < low) {
                    ++high;
                }
                dst[i] += low;
            }
            else {
                dst[i] = low;
            }
            carry = high;
        }
    }
    if (srcParts < dstParts) {
        dst[srcParts] = carry;
        return 0;
    }
    if (carry != 0) {
        return 1;
    }
    if (multiplier != 0) {
        {
            for (uint i = dstParts; i < srcParts; ++i) {
                if (src[i] != 0) {
                    return 1;
                }
            }
        }
    }
    return 0;
}
ulong tcAdd(ulong[] dst, ulong[] rhs, ulong c, uint parts) {
    {
        for (uint i = 0; i < parts; ++i) {
            ulong l = dst[i];
            if (c != 0) {
                dst[i] += rhs[i] + 1;
                if (dst[i] <= l) {
                    c = 1;
                }
                else {
                    c = 0;
                }
            }
            else {
                dst[i] += rhs[i];
                if (dst[i] < l) {
                    c = 1;
                }
                else {
                    c = 0;
                }
            }
        }
    }
    return c;
}
int tcCompare(ulong[] lhs, ulong[] rhs, uint parts) {
    while(parts != 0) {
        --parts;
        if (lhs[parts] != rhs[parts]) {
            return (lhs[parts] > rhs[parts]) ? 1 : -1;
        }
    }
    return 0;
}
/* Negate a bignum in-place.  */
void tcNegate(ulong[] dst, uint parts) {
    .tcComplement(dst, parts);
    .tcIncrement(dst, parts);
}
/* If RHS is zero LHS and REMAINDER are left unchanged, 返回 one.
   Otherwise set LHS to LHS / RHS with the fractional part discarded,
   set REMAINDER to the remainder, 返回 zero.  i.e.

   OLD_LHS = RHS * LHS + REMAINDER

   SCRATCH is a bignum of the same size as the operands and result 循环
   use by the routine; its contents need not be initialized and are
   destroyed.  LHS, REMAINDER and SCRATCH must be distinct.
*/
bool tcDivide(ulong[] lhs, ulong[] rhs, ulong[] remainder, ulong[] srhs, uint parts) {
    uint shiftCount = .tcMSB(rhs, parts) + 1;
    if (shiftCount == 0) {
        return true;
    }
    shiftCount = (cast(uint)(parts * .APINT_BITS_PER_WORD - shiftCount));
    uint n = (cast(uint)(shiftCount / .APINT_BITS_PER_WORD));
    ulong mask = (cast(WordType_)(1)) << (shiftCount % .APINT_BITS_PER_WORD);
    .tcAssign(srhs, rhs, parts);
    .tcShiftLeft(srhs, parts, shiftCount);
    .tcAssign(remainder, lhs, parts);
    .tcSet(lhs, 0, parts);
    /* Loop, subtracting SRHS 如果 REMAINDER is greater and adding that to
    the total.  */
    for (;;) {
        int compare2 = .tcCompare(remainder, srhs, parts);
        if (compare2 >= 0) {
            .tcSubtract(remainder, srhs, 0, parts);
            lhs[n] |= mask;
        }
        if (shiftCount == 0) {
            break;
        }
        --shiftCount;
        .tcShiftRight(srhs, parts, 1);
        if ((mask >>= 1) == 0) {
            mask = (cast(WordType_)(1)) << (.APINT_BITS_PER_WORD - 1);
            --n;
        }
    }
    return false;
}
uint getNumWords(uint BitWidth) {
    return (cast(uint)(((cast(ulong)(BitWidth)) + .APINT_BITS_PER_WORD - 1) / .APINT_BITS_PER_WORD));
}
void udivrem(APInt_ LHS, ulong RHS, ref APInt_ Quotient, ref ulong Remainder) {
    uint bitWidth = LHS.BitWidth;
    if (LHS.isSingleWord()) {
        ulong QuotVal = LHS.U[0] / RHS;
        Remainder = LHS.U[0] % RHS;
        Quotient = new APInt_(bitWidth, QuotVal);
        return;
    }
    uint lhsWords = .getNumWords(LHS.getActiveBits());
    if (lhsWords == 0) {
        Quotient = new APInt_(bitWidth, 0); // 0 / Y ===> 0
        Remainder = 0; // 0 % Y ===> 0
        return;
    }
    if (RHS == 1) {
        Quotient = LHS; // X / 1 ===> X
        Remainder = 0; // X % 1 ===> 0
        return;
    }
    if (LHS.ult(RHS)) {
        Remainder = LHS.getZExtValue(); // X % Y ===> X, iff X < Y
        Quotient = new APInt_(bitWidth, 0); // X / Y ===> 0, iff X < Y
        return;
    }
    if (LHS.Op等等(RHS)) {
        Quotient = new APInt_(bitWidth, 1); // X / X ===> 1
        Remainder = 0; // X % X ===> 0;
        return;
    }
    Quotient.reallocate(bitWidth);
    if (lhsWords == 1) {
        ulong lhsValue = LHS.U[0];
        Quotient.Op等(lhsValue / RHS);
        Remainder = lhsValue % RHS;
        return;
    }
    ulong[] rhs = [RHS];
    ulong[] re = [Remainder];
    .divide(LHS.U, lhsWords, rhs, 1, Quotient.U, re);
    RHS = rhs[0];
    Remainder = re[0];
    .·memset(Quotient.U[lhsWords .. $].ptr, 0, (.getNumWords(bitWidth) - lhsWords) * .APINT_WORD_SIZE);
}
void udivrem_2(APInt_ LHS, APInt_ RHS, ref APInt_ Quotient, ref APInt_ Remainder) {
    uint BitWidth = LHS.BitWidth;
    // First, deal with the easy case
    if (LHS.isSingleWord()) {
        ulong QuotVal = LHS.U[0] / RHS.U[0];
        ulong RemVal = LHS.U[0] % RHS.U[0];
        Quotient = new APInt_(BitWidth, QuotVal);
        Remainder = new APInt_(BitWidth, RemVal);
        return;
    }
    // Get some size facts about the dividend and divisor
    uint lhsWords = .getNumWords(LHS.getActiveBits());
    uint rhsBits = RHS.getActiveBits();
    uint rhsWords = .getNumWords(rhsBits);
    // Check the degenerate cases
    if (lhsWords == 0) {
        Quotient = new APInt_(BitWidth, 0); // 0 / Y ===> 0
        Remainder = new APInt_(BitWidth, 0); // 0 % Y ===> 0
        return;
    }
    if (rhsBits == 1) {
        Quotient = LHS; // X / 1 ===> X
        Remainder = new APInt_(BitWidth, 0); // X % 1 ===> 0
    }
    if (lhsWords < rhsWords || LHS.ult(RHS)) {
        Remainder = LHS; // X % Y ===> X, iff X < Y
        Quotient = new APInt_(BitWidth, 0); // X / Y ===> 0, iff X < Y
        return;
    }
    if (LHS.Op等等(RHS)) {
        Quotient = new APInt_(BitWidth, 1); // X / X ===> 1
        Remainder = new APInt_(BitWidth, 0); // X % X ===> 0;
        return;
    }
    // Make sure there is enough space to hold the results.
    // NOTE: This assumes that reallocate won't affect any bits 如果 it doesn't
    // change the size. This is necessary 如果 Quotient or Remainder is aliased
    // with LHS or RHS.
    Quotient.reallocate(BitWidth);
    Remainder.reallocate(BitWidth);
    if (lhsWords == 1) { // rhsWords is 1 如果 lhsWords is 1.
        // There is only one word to consider so use the native versions.
        ulong lhsValue = LHS.U[0];
        ulong rhsValue = RHS.U[0];
        Quotient.Op等(lhsValue / rhsValue);
        Remainder.Op等(lhsValue % rhsValue);
        return;
    }
    // Okay, lets do it the long way
    .divide(LHS.U, lhsWords, RHS.U, rhsWords, Quotient.U, Remainder.U);
    .·memset(Quotient.U[lhsWords .. $].ptr, 0, (.getNumWords(BitWidth) - lhsWords) * .APINT_WORD_SIZE);
    .·memset(Remainder.U[rhsWords .. $].ptr, 0, (.getNumWords(BitWidth) - rhsWords) * .APINT_WORD_SIZE);
}
void sdivrem(APInt_ LHS, APInt_ RHS, ref APInt_ Quotient, ref APInt_ Remainder) {
    if (LHS.isNegative()) {
        if (RHS.isNegative()) {
            .udivrem_2(LHS.Op负(), RHS.Op负(), Quotient, Remainder);
        }
        else {
            .udivrem_2(LHS.Op负(), RHS, Quotient, Remainder);
            Quotient.negate();
        }
        Remainder.negate();
    }
    else if (RHS.isNegative()) {
        .udivrem_2(LHS, RHS.Op负(), Quotient, Remainder);
        Quotient.negate();
    }
    else {
        .udivrem_2(LHS, RHS, Quotient, Remainder);
    }
}
void divide(ref ulong[] LHS, uint lhsWords, ref ulong[] RHS, uint rhsWords, ref ulong[] Quotient, ref ulong[] Remainder) {
    uint n = rhsWords * 2;
    uint m = (lhsWords * 2) - n;
    uint[] SPACE = 创建数组!(uint)();
    SPACE.length = 128;
    uint[] UU = ··null!(uint[]);
    uint[] V = ··null!(uint[]);
    uint[] Q = ··null!(uint[]);
    uint[] R = ··null!(uint[]);
    if ((Remainder ? 4 : 3) * n + 2 * m + 1 <= 128) {
        UU = SPACE[0 .. $];
        V = SPACE[(m + n + 1) .. $];
        Q = SPACE[((m + n + 1) + n) .. $];
        if (Remainder !is ··null!(ulong[])) {
            R = SPACE[((m + n + 1) + n + (m + n)) .. $];
        }
    }
    else {
        uint[] uarr = 创建数组!(uint)();
        uarr.length = m + n + 1;
        UU = uarr;
        uint[] varr = 创建数组!(uint)();
        uarr.length = n;
        V = varr;
        uint[] qarr = 创建数组!(uint)();
        qarr.length = m + n;
        Q = qarr;
        if (Remainder !is ··null!(ulong[])) {
            uint[] rarr = 创建数组!(uint)();
            rarr.length = n;
            R = rarr;
        }
    }
    .·memset(UU.ptr, 0, 正整数32类型_.sizeof * (m + n + 1));
    {
        for (int i = 0; i < lhsWords; ++i) {
            ulong tmp = LHS[i];
            UU[i * 2] = .Lo_32(tmp);
            UU[i * 2 + 1] = .Hi_32(tmp);
        }
    }
    UU[m + n] = 0;
    .·memset(V.ptr, 0, 正整数32类型_.sizeof * (n));
    {
        for (int i = 0; i < rhsWords; ++i) {
            ulong tmp = RHS[i];
            V[i * 2] = .Lo_32(tmp);
            V[i * 2 + 1] = .Hi_32(tmp);
        }
    }
    .·memset(Q.ptr, 0, 正整数32类型_.sizeof * (m + n));
    if (Remainder !is ··null!(ulong[])) {
        .·memset(R.ptr, 0, 正整数32类型_.sizeof * (n));
    }
    {
        for (uint i = n; i > 0 && V[i - 1] == 0; --i) {
            --n;
            ++m;
        }
    }
    {
        for (uint i = m + n; i > 0 && UU[i - 1] == 0; --i) {
            --m;
        }
    }
    if (n == 1) {
        uint divisor = V[0];
        int remainder = 0;
        {
            for (int i = m; i >= 0; --i) {
                ulong partial_dividend = .Make_64(remainder, UU[i]);
                if (partial_dividend == 0) {
                    Q[i] = 0;
                    remainder = 0;
                }
                else if (partial_dividend < divisor) {
                    Q[i] = 0;
                    remainder = .Lo_32(partial_dividend);
                }
                else if (partial_dividend == divisor) {
                    Q[i] = 1;
                    remainder = 0;
                }
                else {
                    Q[i] = .Lo_32(partial_dividend / divisor);
                    remainder = .Lo_32(partial_dividend - (Q[i] * divisor));
                }
            }
        }
        if (R !is ··null!(uint[])) {
            R[0] = remainder;
        }
    }
    else {
        .KnuthDiv(UU, V, Q, R, m, n);
    }
    // If the caller wants the quotient
    if (Quotient !is ··null!(ulong[])) {
        {
            for (int i = 0; i < lhsWords; ++i) {
                Quotient[i] = .Make_64(Q[i * 2 + 1], Q[i * 2]);
            }
        }
    }
    // If the caller wants the remainder
    if (Remainder !is ··null!(ulong[])) {
        {
            for (int i = 0; i < rhsWords; ++i) {
                Remainder[i] = .Make_64(R[i * 2 + 1], R[i * 2]);
            }
        }
    }
    if (&UU[0] != &SPACE[0]) {
        UU = 返回零值!(uint[])();
        V = 返回零值!(uint[])();
        Q = 返回零值!(uint[])();
        R = 返回零值!(uint[])();
    }
}
APInt_ RoundDoubleToAPInt(double Double, uint width) {
    double dou = Double;
    ulong I = 字节转换!(ulong, double)(dou);
    // Get the sign bit from the highest order bit
    bool isNeg = (I >> 63) != 0;
    // Get the 11-bit exponent and adjust 循环 the 1023 bit bias
    long exp = ((I >> 52) & 2047) - 1023;
    // If the exponent is negative, the value is < 0 so just 返回 0.
    if (exp < 0) {
        return new APInt_(width, 0u);
    }
    // Extract the mantissa by clearing the top 12 bits (sign + exponent).
    ulong mantissa = (I & (~0uL >> 12)) | 1uL << 52;
    // If the exponent doesn't shift all bits out of the mantissa
    if (exp < 52) {
        return isNeg ? (new APInt_(width, mantissa >> (52 - exp))).Op负() : new APInt_(width, mantissa >> (52 - exp));
    }
    // If the client didn't provide enough bits 循环 us to shift the mantissa into
    // then the result is undefined, just 返回 0
    if (width <= exp - 52) {
        return new APInt_(width, 0);
    }
    // Otherwise, we have to shift the mantissa bits up to the right location
    APInt_ Tmp = new APInt_(width, mantissa);
    Tmp.Op左移等((cast(uint)(exp)) - 52);
    return isNeg ? Tmp.Op负() : Tmp;
}
APInt_ GreatestCommonDivisor(APInt_ A, APInt_ B) {
    // Fast-path a common 若是.
    if (A.Op等等(B)) {
        return A;
    }
    // Corner cases: 如果 either operand is zero, the other is the gcd.
    if ((A is ··null!(APInt_)) || A.Op等等(0)) {
        return B;
    }
    if ((B is ··null!(APInt_)) || B.Op等等(0)) {
        return A;
    }
    // Count common powers of 2 and remove all other powers of 2.
    uint Pow2;
    // Both operands are odd multiples of 2^Pow_2:
    //
    //   gcd(a, b) = gcd(|a - b| / 2^i, min(a, b))
    //
    // This is a modified version of Stein's algorithm, taking advantage of
    // efficient countTrailingZeros().
    while(!A.Op等等(B)) {
        if (A.ugt(B)) {
            A.Op减等(B);
            A.lshrInPlace(A.countTrailingZeros() - Pow2);
        }
        else {
            B.Op减等(A);
            B.lshrInPlace(B.countTrailingZeros() - Pow2);
        }
    }
    return A;
}
APInt_ RoundingUDiv(APInt_ A, APInt_ B, Rounding RM) {
    switch (RM) {
        case Rounding.DOWN:
        case Rounding.TOWARD_ZERO: {
            return A.udiv(B);
        }
        case Rounding.UP: {
            APInt_ Quo;
            APInt_ Rem;
            .udivrem_2(A, B, Quo, Rem);
            if (Rem.Op等等(0)) {
                return Quo;
            }
            return .Op_APInt_加_2(Quo, 1);
        }
        default: {
            return 返回零值!(APInt_)();
        }
    }
}
APInt_ RoundingSDiv(APInt_ A, APInt_ B, Rounding RM) {
    switch (RM) {
        case Rounding.DOWN:
        case Rounding.UP: {
            APInt_ Quo;
            APInt_ Rem;
            .sdivrem(A, B, Quo, Rem);
            if (Rem.Op等等(0)) {
                return Quo;
            }
            // This algorithm deals with arbitrary rounding mode used by sdivrem.
            // We want to check whether the non-integer part of the mathematical value
            // is negative or not. If the non-integer part is negative, we need to round
            // down from Quo; otherwise, 如果 it's positive or 0, we 返回 Quo, as it's
            // already rounded down.
            if (RM == Rounding.DOWN) {
                if (Rem.isNegative() != B.isNegative()) {
                    return .Op_APInt_减_2(Quo, 1);
                }
                return Quo;
            }
            if (Rem.isNegative() != B.isNegative()) {
                return Quo;
            }
            return .Op_APInt_加_2(Quo, 1);
        }
        // Currently sdiv rounds towards zero.
        case Rounding.TOWARD_ZERO: {
            return A.sdiv(B);
        }
        default: {
            return 返回零值!(APInt_)();
        }
    }
}
APInt_ SolveQuadraticEquationWrap(APInt_ A, APInt_ B, APInt_ C, uint RangeWidth) {
    APInt_ delegate(APInt_, APInt_) RoundUp;
    uint CoeffWidth;
    APInt_ R;
    APInt_ TwoA;
    APInt_ SqrB;
    bool PickLow;
    APInt_ D2;
    APInt_ SQ;
    APInt_ Q;
    bool InexactSQ;
    APInt_ X;
    APInt_ Rem;
    APInt_ VX;
    APInt_ VY;
    bool SignChange;
    APInt_ RoundUp·func(APInt_ V, APInt_ A) {
        APInt_ T;
        T = V.abs().urem(A);
        if (T.isNullValue()) {
            return V;
        }
        return V.isNegative() ? .Op_APInt_加(V, T) : .Op_APInt_加(V, (.Op_APInt_减(A, T)));
    }
    RoundUp = &RoundUp·func;
    CoeffWidth = A.getBitWidth();
    // Identify 0 as a (non)solution immediately.
    if (C.sextOrTrunc(RangeWidth).isNullValue()) {
        return new APInt_(CoeffWidth, 0);
    }
    // The result of APInt_ arithmetic has the same bit width as the operands,
    // so it can actually lose high bits. A product of two n-bit integers needs
    // 2n-1 bits to represent the full value.
    // The operation done below (on quadratic coefficients) that can produce
    // the largest value is the evaluation of the equation during bisection,
    // which needs 3 times the bitwidth of the coefficient, so the total number
    // of required bits is 3n.
    //
    // The purpose of 本体 extension is to simulate the set Z of all integers,
    // where n+1 > n 循环 all n in Z. In Z it makes sense to talk about positive
    // and negative numbers (not so much in a modulo arithmetic). The method
    // used to solve the equation is based on the standard formula 循环 real
    // numbers, and uses the concepts of "positive" and "negative" with their
    // usual meanings.
    CoeffWidth *= 3;
    A = A.sext(CoeffWidth);
    B = B.sext(CoeffWidth);
    C = C.sext(CoeffWidth);
    // Make A > 0 循环 simplicity. Negate cannot overflow at 本体 point because
    // the bit width has increased.
    if (A.isNegative()) {
        A.negate();
        B.negate();
        C.negate();
    }
    R = .getOneBitSet(CoeffWidth, RangeWidth);
    TwoA = .Op_APInt_乘_2(A, 2);
    SqrB = .Op_APInt_乘(B, B);
    PickLow = false;
    // The vertex of the parabola is at -B/2A, but since A > 0, it's negative
    // iff B is positive.
    if (B.isNonNegative()) {
        // If B >= 0, the vertex it at a negative location (or at 0), so in
        // order to have a non-negative solution we need to pick k that makes
        // C-kR negative. To satisfy all the requirements 循环 the solution
        // that we are looking 循环, it needs to be closest to 0 of all k.
        C = C.srem(R);
        if (C.isStrictlyPositive()) {
            C.Op减等(R);
        }
        // Pick the greater solution.
        PickLow = false;
    }
    else {
        // If B < 0, the vertex is at a positive location. For any solution
        // to exist, the discriminant must be non-negative. This means that
        // C-kR <= B^2/4A is a necessary condition 循环 k, i.e. there is a
        // lower bound on values of k: kR >= C - B^2/4A.
        APInt_ LowkR = .Op_APInt_减(C, SqrB.udiv(.Op_APInt_乘_2(TwoA, 2))); // udiv because all values > 0.
        // Round LowkR up (towards +inf) to the nearest kR.
        LowkR = RoundUp(LowkR, R);
        // If there exists k meeting the condition above, and such that
        // C-kR > 0, there will be two positive real number solutions of
        // q(x) = kR. Out of all such values of k, pick the one that makes
        // C-kR closest to 0, (i.e. pick maximum k such that C-kR > 0).
        // In other words, find maximum k such that LowkR <= kR < C.
        if (C.sgt(LowkR)) {
            // If LowkR < C, then such a k is guaranteed to exist because
            // LowkR itself is a multiple of R.
            C.Op减等(RoundUp(C.Op负(), R).Op负()); // C = C - RoundDown(C, R)
            // Pick the smaller solution.
            PickLow = true;
        }
        else {
            // If C-kR < 0 循环 all potential k's, it means that one solution
            // will be negative, 循环 the other will be positive. The positive
            // solution will shift towards 0 如果 the parabola is moved up.
            // Pick the kR closest to the lower bound (i.e. make C-kR closest
            // to 0, or in other words, out of all parabolas that have solutions,
            // pick the one that is the farthest "up").
            // Since LowkR is itself a multiple of R, simply take C-LowkR.
            C.Op减等(LowkR);
            // Pick the greater solution.
            PickLow = false;
        }
    }
    D2 = .Op_APInt_减(SqrB, .Op_APInt_乘_2(.Op_APInt_乘(A, C), 4));
    SQ = D2.sqrt();
    Q = .Op_APInt_乘(SQ, SQ);
    InexactSQ = !Q.Op等等(D2);
    // The calculated SQ may actually be greater than the exact (non-integer)
    // value. If that's the 若是, decrement SQ to get a value that is lower.
    if (Q.sgt(D2)) {
        SQ.Op减等(1);
    }
    // SQ is rounded down (i.e SQ * SQ <= D), so the roots may be inexact.
    // When using the quadratic formula directly, the calculated low root
    // may be greater than the exact one, since we would be subtracting SQ.
    // To make sure that the calculated root is not greater than the exact
    // one, subtract SQ+1 when calculating the low root (循环 inexact value
    // of SQ).
    if (PickLow) {
        .sdivrem(.Op_APInt_减(B.Op负(), (.Op_APInt_加_2(SQ, InexactSQ ? 1 : 0))), TwoA, X, Rem);
    }
    else {
        .sdivrem(.Op_APInt_加(B.Op负(), SQ), TwoA, X, Rem);
    }
    if (!InexactSQ && Rem.isNullValue()) {
        return X;
    }
    VX = .Op_APInt_加(.Op_APInt_乘((.Op_APInt_加(.Op_APInt_乘(A, X), B)), X), C);
    VY = .Op_APInt_加(.Op_APInt_加(.Op_APInt_加(VX, .Op_APInt_乘(TwoA, X)), A), B);
    SignChange = VX.isNegative() != VY.isNegative() || VX.isNullValue() != VY.isNullValue();
    // If the sign did not change between X and X+1, X is not a valid solution.
    // This could happen when the actual (exact) roots don't have an integer
    // between them, so they would both be contained between X and X+1.
    if (!SignChange) {
        return ··null!(APInt_);
    }
    X.Op加等(1);
    return X;
}
uint GetMostSignificantDifferentBit(APInt_ A, APInt_ B) {
    if (A.Op等等(B)) {
        return ··null!(uint);
    }
    return A.getBitWidth() - ((.OP_APInt_异或(A, B)).countLeadingZeros() + 1);
}
/// StoreIntToMemory - Fills the StoreBytes bytes of memory starting from Dst
/// with the integer held in IntVal.
void StoreIntToMemory(APInt_ IntVal, ubyte[] Dst, uint StoreBytes) {
    ubyte[] Src = (cast(ubyte[])(IntVal.getRawData()));
    if (sys.是小端) {
        // Little-endian host - the source is ordered from LSB to MSB.  Order the
        // destination from LSB to MSB: Do a straight copy.
        .·memcpy(Dst.ptr, Src.ptr, StoreBytes);
    }
    else {
        // Big-endian host - the source is an array of 64 bit words ordered from
        // LSW to MSW.  Each word is ordered from MSB to LSB.  Order the destination
        // from MSB to LSB: Reverse the word order, but not the bytes in a word.
        while(StoreBytes > WordType_.sizeof) {
            StoreBytes -= (cast(uint)(WordType_.sizeof));
            // May not be aligned so use memcpy.
            .·memcpy(Dst[StoreBytes .. $].ptr, Src.ptr, WordType_.sizeof);
            Src = Src[WordType_.sizeof .. $];
        }
        .·memcpy(Dst.ptr, Src[WordType_.sizeof - StoreBytes .. $].ptr, StoreBytes);
    }
}
/// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting
/// from Src into IntVal, which is assumed to be wide enough and to hold zero.
void LoadIntFromMemory(APInt_ IntVal, ubyte[] Src, uint LoadBytes) {
    ubyte[] Dst = (cast(ubyte[])((IntVal.getRawData())));
    if (sys.是小端) {
        // Little-endian host - the destination must be ordered from LSB to MSB.
        // The source is ordered from LSB to MSB: Do a straight copy.
        .·memcpy(Dst.ptr, Src.ptr, LoadBytes);
    }
    else {
        // Big-endian - the destination is an array of 64 bit words ordered from
        // LSW to MSW.  Each word must be ordered from MSB to LSB.  The source is
        // ordered from MSB to LSB: Reverse the word order, but not the bytes in
        // a word.
        while(LoadBytes > WordType_.sizeof) {
            LoadBytes -= (cast(uint)(WordType_.sizeof));
            // May not be aligned so use memcpy.
            .·memcpy(Dst.ptr, Src[LoadBytes .. $].ptr, WordType_.sizeof);
            Dst = Dst[WordType_.sizeof .. $];
        }
        .·memcpy(Dst[WordType_.sizeof - LoadBytes .. $].ptr, Src.ptr, LoadBytes);
    }
    IntVal.U = bitTo!(ulong[], ubyte[])(Dst);
}
APInt_ getOneBitSet(uint numBits, uint BitNo) {
    APInt_ Res = new APInt_(numBits, 0);
    Res.setBit(BitNo);
    return Res;
}
// Calculate the rotate amount modulo the bit width.
uint rotateModulo(uint BitWidth, APInt_ rotateAmt) {
    uint rotBitWidth = rotateAmt.getBitWidth();
    APInt_ rot = rotateAmt;
    if (rotBitWidth < BitWidth) {
        // Extend the rotate APInt_, so that the urem doesn't divide by 0.
        // e.g. APInt_(1, 32) would give APInt_(1, 0).
        rot = rotateAmt.zext(BitWidth);
    }
    rot = rot.urem(new APInt_(rot.getBitWidth(), BitWidth));
    return (cast(uint)(rot.getLimitedValue(BitWidth)));
}
/// Determine 如果 two APInts have the same value, after zero-extending
/// one of them (如果 needed!) to ensure that the bit-widths match.
bool isSameValue(APInt_ I1, APInt_ I2) {
    if (I1.getBitWidth() == I2.getBitWidth()) {
        return I1.Op等等(I2);
    }
    if (I1.getBitWidth() > I2.getBitWidth()) {
        return I1.Op等等(I2.zext(I1.getBitWidth()));
    }
    return (I1.zext(I2.getBitWidth())).Op等等(I2);
}
/// Return true if the argument is a power of two > 0.
/// Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.)
bool isPowerOf2_32(uint Value) {
    return Value != 0 && (Value & (Value - 1)) == 0;
}
/// Return true if the argument is a power of two > 0 (64 bit edition.)
bool isPowerOf2_64(ulong Value) {
    return Value != 0 && (Value & (Value - 1)) == 0;
}
/// Return true if the argument is a non-empty sequence of ones starting at the
/// least significant bit with the remainder zero (64 bit version).
bool isMask_64(ulong Value) {
    return Value != 0 && ((Value + 1) & Value) == 0;
}
/// Return true if the argument contains a non-empty sequence of ones with the
/// remainder zero (64 bit version.)
bool isShiftedMask_64(ulong Value) {
    return Value != 0 && .isMask_64((Value - 1) | Value);
}
APInt_ Op负(APInt_ v) {
    v.negate();
    return v;
}
APInt_ Op_APInt_乘(APInt_ a, APInt_ b) {
    APInt_ r = a;
    return r.Op乘(b);
}
APInt_ Op_APInt_乘_2(APInt_ a, ulong b) {
    APInt_ r = a;
    return r.Op乘等(b);
}
APInt_ Op_APInt_加(APInt_ a, APInt_ b) {
    APInt_ r = a;
    r.Op加等(b);
    return r;
}
APInt_ Op_APInt_加_2(APInt_ a, ulong b) {
    APInt_ r = a;
    r.Op加等(b);
    return r;
}
APInt_ Op_APInt_减(APInt_ a, APInt_ b) {
    APInt_ r = a;
    r.Op减等(b);
    return r;
}
APInt_ Op_APInt_减_2(APInt_ a, ulong b) {
    APInt_ r = a;
    r.Op减等(b);
    return r;
}
APInt_ OP_APInt_异或(APInt_ a, APInt_ b) {
    APInt_ r = a;
    r.Op异或等(b);
    return r;
}
APInt_ OP_APInt_异或_2(APInt_ a, ulong b) {
    APInt_ r = a;
    r.Op异或等(b);
    return r;
}
/// Converts a 小数64 to APInt_ bits.
///
/// The conversion does not do a translation from 小数64 to integer, it just
/// re-interprets the bits of the 小数64.
APInt_ doubleToBits(double V) {
    return new APInt_((cast(uint)(V.sizeof * .CHAR_BIT)), DoubleToBits(V));
}
/// Converts a 小数32 to APInt_ bits.
///
/// The conversion does not do a translation from 小数32 to integer, it just
/// re-interprets the bits of the 小数32.
APInt_ floatToBits(float V) {
    return new APInt_((cast(uint)(V.sizeof * .CHAR_BIT)), FloatToBits(V));
}
unittest {
    void main() {
        ulong[] a = [222222, 111111];
        APInt_ n1 = new APInt_(128, a);
        .·writeln(n1.U);
        APInt_ n2 = new APInt_(128, a);
        n1.Op加等(n2);
        .·writeln(n1.U);
        dstring str = "18446744073709551614"d;
        APInt_ s = new APInt_(128, str, 10);
        s.Op加等(1);
        .·writeln(s.打印());
    }
    main();
}
